1143 lines
23 KiB
ArmAsm
1143 lines
23 KiB
ArmAsm
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||
|
/*
|
||
|
* arch/arm/mach-at91/pm_slow_clock.S
|
||
|
*
|
||
|
* Copyright (C) 2006 Savin Zlobec
|
||
|
*
|
||
|
* AT91SAM9 support:
|
||
|
* Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee>
|
||
|
*/
|
||
|
#include <linux/linkage.h>
|
||
|
#include <linux/clk/at91_pmc.h>
|
||
|
#include "pm.h"
|
||
|
#include "pm_data-offsets.h"
|
||
|
|
||
|
#define SRAMC_SELF_FRESH_ACTIVE 0x01
|
||
|
#define SRAMC_SELF_FRESH_EXIT 0x00
|
||
|
|
||
|
pmc .req r0
|
||
|
tmp1 .req r4
|
||
|
tmp2 .req r5
|
||
|
tmp3 .req r6
|
||
|
|
||
|
/*
|
||
|
* Wait until master clock is ready (after switching master clock source)
|
||
|
*
|
||
|
* @r_mckid: register holding master clock identifier
|
||
|
*
|
||
|
* Side effects: overwrites r7, r8
|
||
|
*/
|
||
|
.macro wait_mckrdy r_mckid
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
cmp \r_mckid, #0
|
||
|
beq 1f
|
||
|
mov r7, #AT91_PMC_MCKXRDY
|
||
|
b 2f
|
||
|
#endif
|
||
|
1: mov r7, #AT91_PMC_MCKRDY
|
||
|
2: ldr r8, [pmc, #AT91_PMC_SR]
|
||
|
and r8, r7
|
||
|
cmp r8, r7
|
||
|
bne 2b
|
||
|
.endm
|
||
|
|
||
|
/*
|
||
|
* Wait until master oscillator has stabilized.
|
||
|
*
|
||
|
* Side effects: overwrites r7
|
||
|
*/
|
||
|
.macro wait_moscrdy
|
||
|
1: ldr r7, [pmc, #AT91_PMC_SR]
|
||
|
tst r7, #AT91_PMC_MOSCS
|
||
|
beq 1b
|
||
|
.endm
|
||
|
|
||
|
/*
|
||
|
* Wait for main oscillator selection is done
|
||
|
*
|
||
|
* Side effects: overwrites r7
|
||
|
*/
|
||
|
.macro wait_moscsels
|
||
|
1: ldr r7, [pmc, #AT91_PMC_SR]
|
||
|
tst r7, #AT91_PMC_MOSCSELS
|
||
|
beq 1b
|
||
|
.endm
|
||
|
|
||
|
/*
|
||
|
* Put the processor to enter the idle state
|
||
|
*
|
||
|
* Side effects: overwrites r7
|
||
|
*/
|
||
|
.macro at91_cpu_idle
|
||
|
|
||
|
#if defined(CONFIG_CPU_V7)
|
||
|
mov r7, #AT91_PMC_PCK
|
||
|
str r7, [pmc, #AT91_PMC_SCDR]
|
||
|
|
||
|
dsb
|
||
|
|
||
|
wfi @ Wait For Interrupt
|
||
|
#else
|
||
|
mcr p15, 0, tmp1, c7, c0, 4
|
||
|
#endif
|
||
|
|
||
|
.endm
|
||
|
|
||
|
/**
|
||
|
* Set state for 2.5V low power regulator
|
||
|
* @ena: 0 - disable regulator
|
||
|
* 1 - enable regulator
|
||
|
*
|
||
|
* Side effects: overwrites r7, r8, r9, r10
|
||
|
*/
|
||
|
.macro at91_2_5V_reg_set_low_power ena
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
ldr r7, .sfrbu
|
||
|
mov r8, #\ena
|
||
|
ldr r9, [r7, #AT91_SFRBU_25LDOCR]
|
||
|
orr r9, r9, #AT91_SFRBU_25LDOCR_LP
|
||
|
cmp r8, #1
|
||
|
beq lp_done_\ena
|
||
|
bic r9, r9, #AT91_SFRBU_25LDOCR_LP
|
||
|
lp_done_\ena:
|
||
|
ldr r10, =AT91_SFRBU_25LDOCR_LDOANAKEY
|
||
|
orr r9, r9, r10
|
||
|
str r9, [r7, #AT91_SFRBU_25LDOCR]
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
.macro at91_backup_set_lpm reg
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
orr \reg, \reg, #0x200000
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
.text
|
||
|
|
||
|
.arm
|
||
|
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
/**
|
||
|
* Enable self-refresh
|
||
|
*
|
||
|
* Side effects: overwrites r2, r3, tmp1, tmp2, tmp3, r7
|
||
|
*/
|
||
|
.macro at91_sramc_self_refresh_ena
|
||
|
ldr r2, .sramc_base
|
||
|
ldr r3, .sramc_phy_base
|
||
|
ldr r7, .pm_mode
|
||
|
|
||
|
dsb
|
||
|
|
||
|
/* Disable all AXI ports. */
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_0]
|
||
|
bic tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_0]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_1]
|
||
|
bic tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_1]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_2]
|
||
|
bic tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_2]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_3]
|
||
|
bic tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_3]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_4]
|
||
|
bic tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_4]
|
||
|
|
||
|
sr_ena_1:
|
||
|
/* Wait for all ports to disable. */
|
||
|
ldr tmp1, [r2, #UDDRC_PSTAT]
|
||
|
ldr tmp2, =UDDRC_PSTAT_ALL_PORTS
|
||
|
tst tmp1, tmp2
|
||
|
bne sr_ena_1
|
||
|
|
||
|
/* Switch to self-refresh. */
|
||
|
ldr tmp1, [r2, #UDDRC_PWRCTL]
|
||
|
orr tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW
|
||
|
str tmp1, [r2, #UDDRC_PWRCTL]
|
||
|
|
||
|
sr_ena_2:
|
||
|
/* Wait for self-refresh enter. */
|
||
|
ldr tmp1, [r2, #UDDRC_STAT]
|
||
|
bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
|
||
|
cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
|
||
|
bne sr_ena_2
|
||
|
|
||
|
/* Put DDR PHY's DLL in bypass mode for non-backup modes. */
|
||
|
cmp r7, #AT91_PM_BACKUP
|
||
|
beq sr_ena_3
|
||
|
ldr tmp1, [r3, #DDR3PHY_PIR]
|
||
|
orr tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
|
||
|
str tmp1, [r3, #DDR3PHY_PIR]
|
||
|
|
||
|
sr_ena_3:
|
||
|
/* Power down DDR PHY data receivers. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_DXCCR]
|
||
|
orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
|
||
|
str tmp1, [r3, #DDR3PHY_DXCCR]
|
||
|
|
||
|
/* Power down ADDR/CMD IO. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_ACIOCR]
|
||
|
orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
|
||
|
orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
|
||
|
orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
|
||
|
str tmp1, [r3, #DDR3PHY_ACIOCR]
|
||
|
|
||
|
/* Power down ODT. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_DSGCR]
|
||
|
orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
|
||
|
str tmp1, [r3, #DDR3PHY_DSGCR]
|
||
|
.endm
|
||
|
|
||
|
/**
|
||
|
* Disable self-refresh
|
||
|
*
|
||
|
* Side effects: overwrites r2, r3, tmp1, tmp2, tmp3
|
||
|
*/
|
||
|
.macro at91_sramc_self_refresh_dis
|
||
|
ldr r2, .sramc_base
|
||
|
ldr r3, .sramc_phy_base
|
||
|
|
||
|
/* Power up DDR PHY data receivers. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_DXCCR]
|
||
|
bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
|
||
|
str tmp1, [r3, #DDR3PHY_DXCCR]
|
||
|
|
||
|
/* Power up the output of CK and CS pins. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_ACIOCR]
|
||
|
bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
|
||
|
bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
|
||
|
bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
|
||
|
str tmp1, [r3, #DDR3PHY_ACIOCR]
|
||
|
|
||
|
/* Power up ODT. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_DSGCR]
|
||
|
bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
|
||
|
str tmp1, [r3, #DDR3PHY_DSGCR]
|
||
|
|
||
|
/* Take DDR PHY's DLL out of bypass mode. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_PIR]
|
||
|
bic tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
|
||
|
str tmp1, [r3, #DDR3PHY_PIR]
|
||
|
|
||
|
/* Enable quasi-dynamic programming. */
|
||
|
mov tmp1, #0
|
||
|
str tmp1, [r2, #UDDRC_SWCTRL]
|
||
|
|
||
|
/* De-assert SDRAM initialization. */
|
||
|
ldr tmp1, [r2, #UDDRC_DFIMISC]
|
||
|
bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
|
||
|
str tmp1, [r2, #UDDRC_DFIMISC]
|
||
|
|
||
|
/* Quasi-dynamic programming done. */
|
||
|
mov tmp1, #UDDRC_SWCTRL_SW_DONE
|
||
|
str tmp1, [r2, #UDDRC_SWCTRL]
|
||
|
|
||
|
sr_dis_1:
|
||
|
ldr tmp1, [r2, #UDDRC_SWSTAT]
|
||
|
tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
|
||
|
beq sr_dis_1
|
||
|
|
||
|
/* DLL soft-reset + DLL lock wait + ITM reset */
|
||
|
mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
|
||
|
DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
|
||
|
str tmp1, [r3, #DDR3PHY_PIR]
|
||
|
|
||
|
sr_dis_4:
|
||
|
/* Wait for it. */
|
||
|
ldr tmp1, [r3, #DDR3PHY_PGSR]
|
||
|
tst tmp1, #DDR3PHY_PGSR_IDONE
|
||
|
beq sr_dis_4
|
||
|
|
||
|
/* Enable quasi-dynamic programming. */
|
||
|
mov tmp1, #0
|
||
|
str tmp1, [r2, #UDDRC_SWCTRL]
|
||
|
|
||
|
/* Assert PHY init complete enable signal. */
|
||
|
ldr tmp1, [r2, #UDDRC_DFIMISC]
|
||
|
orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
|
||
|
str tmp1, [r2, #UDDRC_DFIMISC]
|
||
|
|
||
|
/* Programming is done. Set sw_done. */
|
||
|
mov tmp1, #UDDRC_SWCTRL_SW_DONE
|
||
|
str tmp1, [r2, #UDDRC_SWCTRL]
|
||
|
|
||
|
sr_dis_5:
|
||
|
/* Wait for it. */
|
||
|
ldr tmp1, [r2, #UDDRC_SWSTAT]
|
||
|
tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
|
||
|
beq sr_dis_5
|
||
|
|
||
|
/* Trigger self-refresh exit. */
|
||
|
ldr tmp1, [r2, #UDDRC_PWRCTL]
|
||
|
bic tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW
|
||
|
str tmp1, [r2, #UDDRC_PWRCTL]
|
||
|
|
||
|
sr_dis_6:
|
||
|
/* Wait for self-refresh exit done. */
|
||
|
ldr tmp1, [r2, #UDDRC_STAT]
|
||
|
bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
|
||
|
cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL
|
||
|
bne sr_dis_6
|
||
|
|
||
|
/* Enable all AXI ports. */
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_0]
|
||
|
orr tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_0]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_1]
|
||
|
orr tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_1]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_2]
|
||
|
orr tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_2]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_3]
|
||
|
orr tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_3]
|
||
|
|
||
|
ldr tmp1, [r2, #UDDRC_PCTRL_4]
|
||
|
orr tmp1, tmp1, #0x1
|
||
|
str tmp1, [r2, #UDDRC_PCTRL_4]
|
||
|
|
||
|
dsb
|
||
|
.endm
|
||
|
#else
|
||
|
/**
|
||
|
* Enable self-refresh
|
||
|
*
|
||
|
* register usage:
|
||
|
* @r1: memory type
|
||
|
* @r2: base address of the sram controller
|
||
|
* @r3: temporary
|
||
|
*/
|
||
|
.macro at91_sramc_self_refresh_ena
|
||
|
ldr r1, .memtype
|
||
|
ldr r2, .sramc_base
|
||
|
|
||
|
cmp r1, #AT91_MEMCTRL_MC
|
||
|
bne sr_ena_ddrc_sf
|
||
|
|
||
|
/* Active SDRAM self-refresh mode */
|
||
|
mov r3, #1
|
||
|
str r3, [r2, #AT91_MC_SDRAMC_SRR]
|
||
|
b sr_ena_exit
|
||
|
|
||
|
sr_ena_ddrc_sf:
|
||
|
cmp r1, #AT91_MEMCTRL_DDRSDR
|
||
|
bne sr_ena_sdramc_sf
|
||
|
|
||
|
/*
|
||
|
* DDR Memory controller
|
||
|
*/
|
||
|
|
||
|
/* LPDDR1 --> force DDR2 mode during self-refresh */
|
||
|
ldr r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
str r3, .saved_sam9_mdr
|
||
|
bic r3, r3, #~AT91_DDRSDRC_MD
|
||
|
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
|
||
|
ldreq r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
biceq r3, r3, #AT91_DDRSDRC_MD
|
||
|
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
|
||
|
streq r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
|
||
|
/* Active DDRC self-refresh mode */
|
||
|
ldr r3, [r2, #AT91_DDRSDRC_LPR]
|
||
|
str r3, .saved_sam9_lpr
|
||
|
bic r3, r3, #AT91_DDRSDRC_LPCB
|
||
|
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
|
||
|
str r3, [r2, #AT91_DDRSDRC_LPR]
|
||
|
|
||
|
/* If using the 2nd ddr controller */
|
||
|
ldr r2, .sramc1_base
|
||
|
cmp r2, #0
|
||
|
beq sr_ena_no_2nd_ddrc
|
||
|
|
||
|
ldr r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
str r3, .saved_sam9_mdr1
|
||
|
bic r3, r3, #~AT91_DDRSDRC_MD
|
||
|
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
|
||
|
ldreq r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
biceq r3, r3, #AT91_DDRSDRC_MD
|
||
|
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
|
||
|
streq r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
|
||
|
/* Active DDRC self-refresh mode */
|
||
|
ldr r3, [r2, #AT91_DDRSDRC_LPR]
|
||
|
str r3, .saved_sam9_lpr1
|
||
|
bic r3, r3, #AT91_DDRSDRC_LPCB
|
||
|
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
|
||
|
str r3, [r2, #AT91_DDRSDRC_LPR]
|
||
|
|
||
|
sr_ena_no_2nd_ddrc:
|
||
|
b sr_ena_exit
|
||
|
|
||
|
/*
|
||
|
* SDRAMC Memory controller
|
||
|
*/
|
||
|
sr_ena_sdramc_sf:
|
||
|
/* Active SDRAMC self-refresh mode */
|
||
|
ldr r3, [r2, #AT91_SDRAMC_LPR]
|
||
|
str r3, .saved_sam9_lpr
|
||
|
bic r3, r3, #AT91_SDRAMC_LPCB
|
||
|
orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
|
||
|
str r3, [r2, #AT91_SDRAMC_LPR]
|
||
|
|
||
|
ldr r3, .saved_sam9_lpr
|
||
|
str r3, [r2, #AT91_SDRAMC_LPR]
|
||
|
|
||
|
sr_ena_exit:
|
||
|
.endm
|
||
|
|
||
|
/**
|
||
|
* Disable self-refresh
|
||
|
*
|
||
|
* register usage:
|
||
|
* @r1: memory type
|
||
|
* @r2: base address of the sram controller
|
||
|
* @r3: temporary
|
||
|
*/
|
||
|
.macro at91_sramc_self_refresh_dis
|
||
|
ldr r1, .memtype
|
||
|
ldr r2, .sramc_base
|
||
|
|
||
|
cmp r1, #AT91_MEMCTRL_MC
|
||
|
bne sr_dis_ddrc_exit_sf
|
||
|
|
||
|
/*
|
||
|
* at91rm9200 Memory controller
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* For exiting the self-refresh mode, do nothing,
|
||
|
* automatically exit the self-refresh mode.
|
||
|
*/
|
||
|
b sr_dis_exit
|
||
|
|
||
|
sr_dis_ddrc_exit_sf:
|
||
|
cmp r1, #AT91_MEMCTRL_DDRSDR
|
||
|
bne sdramc_exit_sf
|
||
|
|
||
|
/* DDR Memory controller */
|
||
|
|
||
|
/* Restore MDR in case of LPDDR1 */
|
||
|
ldr r3, .saved_sam9_mdr
|
||
|
str r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
/* Restore LPR on AT91 with DDRAM */
|
||
|
ldr r3, .saved_sam9_lpr
|
||
|
str r3, [r2, #AT91_DDRSDRC_LPR]
|
||
|
|
||
|
/* If using the 2nd ddr controller */
|
||
|
ldr r2, .sramc1_base
|
||
|
cmp r2, #0
|
||
|
ldrne r3, .saved_sam9_mdr1
|
||
|
strne r3, [r2, #AT91_DDRSDRC_MDR]
|
||
|
ldrne r3, .saved_sam9_lpr1
|
||
|
strne r3, [r2, #AT91_DDRSDRC_LPR]
|
||
|
|
||
|
b sr_dis_exit
|
||
|
|
||
|
sdramc_exit_sf:
|
||
|
/* SDRAMC Memory controller */
|
||
|
ldr r3, .saved_sam9_lpr
|
||
|
str r3, [r2, #AT91_SDRAMC_LPR]
|
||
|
|
||
|
sr_dis_exit:
|
||
|
.endm
|
||
|
#endif
|
||
|
|
||
|
.macro at91_pm_ulp0_mode
|
||
|
ldr pmc, .pmc_base
|
||
|
ldr tmp2, .pm_mode
|
||
|
ldr tmp3, .mckr_offset
|
||
|
|
||
|
/* Check if ULP0 fast variant has been requested. */
|
||
|
cmp tmp2, #AT91_PM_ULP0_FAST
|
||
|
bne 0f
|
||
|
|
||
|
/* Set highest prescaler for power saving */
|
||
|
ldr tmp1, [pmc, tmp3]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PRES
|
||
|
orr tmp1, tmp1, #AT91_PMC_PRES_64
|
||
|
str tmp1, [pmc, tmp3]
|
||
|
|
||
|
mov tmp3, #0
|
||
|
wait_mckrdy tmp3
|
||
|
b 1f
|
||
|
|
||
|
0:
|
||
|
/* Turn off the crystal oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
bic tmp1, tmp1, #AT91_PMC_MOSCEN
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Save RC oscillator state */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
str tmp1, .saved_osc_status
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
bne 1f
|
||
|
|
||
|
/* Turn off RC oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
bic tmp1, tmp1, #AT91_PMC_MOSCRCEN
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Wait main RC disabled done */
|
||
|
2: ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
bne 2b
|
||
|
|
||
|
/* Wait for interrupt */
|
||
|
1: at91_cpu_idle
|
||
|
|
||
|
/* Check if ULP0 fast variant has been requested. */
|
||
|
cmp tmp2, #AT91_PM_ULP0_FAST
|
||
|
bne 5f
|
||
|
|
||
|
/* Set lowest prescaler for fast resume. */
|
||
|
ldr tmp3, .mckr_offset
|
||
|
ldr tmp1, [pmc, tmp3]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PRES
|
||
|
str tmp1, [pmc, tmp3]
|
||
|
|
||
|
mov tmp3, #0
|
||
|
wait_mckrdy tmp3
|
||
|
b 6f
|
||
|
|
||
|
5: /* Restore RC oscillator state */
|
||
|
ldr tmp1, .saved_osc_status
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
beq 4f
|
||
|
|
||
|
/* Turn on RC oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
orr tmp1, tmp1, #AT91_PMC_MOSCRCEN
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Wait main RC stabilization */
|
||
|
3: ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
beq 3b
|
||
|
|
||
|
/* Turn on the crystal oscillator */
|
||
|
4: ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
orr tmp1, tmp1, #AT91_PMC_MOSCEN
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
wait_moscrdy
|
||
|
6:
|
||
|
.endm
|
||
|
|
||
|
/**
|
||
|
* Note: This procedure only applies on the platform which uses
|
||
|
* the external crystal oscillator as a main clock source.
|
||
|
*/
|
||
|
.macro at91_pm_ulp1_mode
|
||
|
ldr pmc, .pmc_base
|
||
|
ldr tmp2, .mckr_offset
|
||
|
mov tmp3, #0
|
||
|
|
||
|
/* Save RC oscillator state and check if it is enabled. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
str tmp1, .saved_osc_status
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
bne 2f
|
||
|
|
||
|
/* Enable RC oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
orr tmp1, tmp1, #AT91_PMC_MOSCRCEN
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Wait main RC stabilization */
|
||
|
1: ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
beq 1b
|
||
|
|
||
|
/* Switch the main clock source to 12-MHz RC oscillator */
|
||
|
2: ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
bic tmp1, tmp1, #AT91_PMC_MOSCSEL
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
wait_moscsels
|
||
|
|
||
|
/* Disable the crystal oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
bic tmp1, tmp1, #AT91_PMC_MOSCEN
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Switch the master clock source to main clock */
|
||
|
ldr tmp1, [pmc, tmp2]
|
||
|
bic tmp1, tmp1, #AT91_PMC_CSS
|
||
|
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
|
||
|
str tmp1, [pmc, tmp2]
|
||
|
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
orr tmp1, tmp1, #AT91_PMC_WAITMODE
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Quirk for SAM9X60's PMC */
|
||
|
nop
|
||
|
nop
|
||
|
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
/* Enable the crystal oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
orr tmp1, tmp1, #AT91_PMC_MOSCEN
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
wait_moscrdy
|
||
|
|
||
|
/* Switch the master clock source to slow clock */
|
||
|
ldr tmp1, [pmc, tmp2]
|
||
|
bic tmp1, tmp1, #AT91_PMC_CSS
|
||
|
str tmp1, [pmc, tmp2]
|
||
|
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
/* Switch main clock source to crystal oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
orr tmp1, tmp1, #AT91_PMC_MOSCSEL
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
wait_moscsels
|
||
|
|
||
|
/* Switch the master clock source to main clock */
|
||
|
ldr tmp1, [pmc, tmp2]
|
||
|
bic tmp1, tmp1, #AT91_PMC_CSS
|
||
|
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
|
||
|
str tmp1, [pmc, tmp2]
|
||
|
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
/* Restore RC oscillator state */
|
||
|
ldr tmp1, .saved_osc_status
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
bne 3f
|
||
|
|
||
|
/* Disable RC oscillator */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
bic tmp1, tmp1, #AT91_PMC_MOSCRCEN
|
||
|
bic tmp1, tmp1, #AT91_PMC_KEY_MASK
|
||
|
orr tmp1, tmp1, #AT91_PMC_KEY
|
||
|
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||
|
|
||
|
/* Wait RC oscillator disable done */
|
||
|
4: ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
tst tmp1, #AT91_PMC_MOSCRCS
|
||
|
bne 4b
|
||
|
|
||
|
3:
|
||
|
.endm
|
||
|
|
||
|
.macro at91_plla_disable
|
||
|
/* Save PLLA setting and disable it */
|
||
|
ldr tmp1, .pmc_version
|
||
|
cmp tmp1, #AT91_PMC_V1
|
||
|
beq 1f
|
||
|
|
||
|
#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
|
||
|
/* Save PLLA settings. */
|
||
|
ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
|
||
|
str tmp2, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
/* save div. */
|
||
|
mov tmp1, #0
|
||
|
ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
bic tmp2, tmp2, #0xffffff00
|
||
|
orr tmp1, tmp1, tmp2
|
||
|
|
||
|
/* save mul. */
|
||
|
ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL1]
|
||
|
bic tmp2, tmp2, #0xffffff
|
||
|
orr tmp1, tmp1, tmp2
|
||
|
str tmp1, .saved_pllar
|
||
|
|
||
|
/* step 2. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
/* step 3. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
|
||
|
/* step 4. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
/* step 5. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
|
||
|
/* step 7. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
b 2f
|
||
|
#endif
|
||
|
|
||
|
1: /* Save PLLA setting and disable it */
|
||
|
ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
|
||
|
str tmp1, .saved_pllar
|
||
|
|
||
|
/* Disable PLLA. */
|
||
|
mov tmp1, #AT91_PMC_PLLCOUNT
|
||
|
orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
|
||
|
str tmp1, [pmc, #AT91_CKGR_PLLAR]
|
||
|
2:
|
||
|
.endm
|
||
|
|
||
|
.macro at91_plla_enable
|
||
|
ldr tmp2, .saved_pllar
|
||
|
ldr tmp3, .pmc_version
|
||
|
cmp tmp3, #AT91_PMC_V1
|
||
|
beq 4f
|
||
|
|
||
|
#ifdef CONFIG_HAVE_AT91_SAM9X60_PLL
|
||
|
/* step 1. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
/* step 2. */
|
||
|
ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_ACR]
|
||
|
|
||
|
/* step 3. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
|
||
|
mov tmp3, tmp2
|
||
|
bic tmp3, tmp3, #0xffffff
|
||
|
orr tmp1, tmp1, tmp3
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
|
||
|
|
||
|
/* step 8. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
/* step 9. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
|
||
|
bic tmp1, tmp1, #0xff
|
||
|
mov tmp3, tmp2
|
||
|
bic tmp3, tmp3, #0xffffff00
|
||
|
orr tmp1, tmp1, tmp3
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
|
||
|
|
||
|
/* step 10. */
|
||
|
ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
|
||
|
bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
|
||
|
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||
|
|
||
|
/* step 11. */
|
||
|
3: ldr tmp1, [pmc, #AT91_PMC_PLL_ISR0]
|
||
|
tst tmp1, #0x1
|
||
|
beq 3b
|
||
|
b 2f
|
||
|
#endif
|
||
|
|
||
|
/* Restore PLLA setting */
|
||
|
4: str tmp2, [pmc, #AT91_CKGR_PLLAR]
|
||
|
|
||
|
/* Enable PLLA. */
|
||
|
tst tmp2, #(AT91_PMC_MUL & 0xff0000)
|
||
|
bne 1f
|
||
|
tst tmp2, #(AT91_PMC_MUL & ~0xff0000)
|
||
|
beq 2f
|
||
|
|
||
|
1: ldr tmp1, [pmc, #AT91_PMC_SR]
|
||
|
tst tmp1, #AT91_PMC_LOCKA
|
||
|
beq 1b
|
||
|
2:
|
||
|
.endm
|
||
|
|
||
|
/**
|
||
|
* at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock
|
||
|
*
|
||
|
* Side effects: overwrites tmp1, tmp2
|
||
|
*/
|
||
|
.macro at91_mckx_ps_enable
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
ldr pmc, .pmc_base
|
||
|
|
||
|
/* There are 4 MCKs we need to handle: MCK1..4 */
|
||
|
mov tmp1, #1
|
||
|
e_loop: cmp tmp1, #5
|
||
|
beq e_done
|
||
|
|
||
|
/* Write MCK ID to retrieve the settings. */
|
||
|
str tmp1, [pmc, #AT91_PMC_MCR_V2]
|
||
|
ldr tmp2, [pmc, #AT91_PMC_MCR_V2]
|
||
|
|
||
|
e_save_mck1:
|
||
|
cmp tmp1, #1
|
||
|
bne e_save_mck2
|
||
|
str tmp2, .saved_mck1
|
||
|
b e_ps
|
||
|
|
||
|
e_save_mck2:
|
||
|
cmp tmp1, #2
|
||
|
bne e_save_mck3
|
||
|
str tmp2, .saved_mck2
|
||
|
b e_ps
|
||
|
|
||
|
e_save_mck3:
|
||
|
cmp tmp1, #3
|
||
|
bne e_save_mck4
|
||
|
str tmp2, .saved_mck3
|
||
|
b e_ps
|
||
|
|
||
|
e_save_mck4:
|
||
|
str tmp2, .saved_mck4
|
||
|
|
||
|
e_ps:
|
||
|
/* Use CSS=MAINCK and DIV=1. */
|
||
|
bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS
|
||
|
bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV
|
||
|
orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MAINCK
|
||
|
orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV1
|
||
|
str tmp2, [pmc, #AT91_PMC_MCR_V2]
|
||
|
|
||
|
wait_mckrdy tmp1
|
||
|
|
||
|
add tmp1, tmp1, #1
|
||
|
b e_loop
|
||
|
|
||
|
e_done:
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
/**
|
||
|
* at91_mckx_ps_restore: restore MCK1..4 settings
|
||
|
*
|
||
|
* Side effects: overwrites tmp1, tmp2
|
||
|
*/
|
||
|
.macro at91_mckx_ps_restore
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
ldr pmc, .pmc_base
|
||
|
|
||
|
/* There are 4 MCKs we need to handle: MCK1..4 */
|
||
|
mov tmp1, #1
|
||
|
r_loop: cmp tmp1, #5
|
||
|
beq r_done
|
||
|
|
||
|
r_save_mck1:
|
||
|
cmp tmp1, #1
|
||
|
bne r_save_mck2
|
||
|
ldr tmp2, .saved_mck1
|
||
|
b r_ps
|
||
|
|
||
|
r_save_mck2:
|
||
|
cmp tmp1, #2
|
||
|
bne r_save_mck3
|
||
|
ldr tmp2, .saved_mck2
|
||
|
b r_ps
|
||
|
|
||
|
r_save_mck3:
|
||
|
cmp tmp1, #3
|
||
|
bne r_save_mck4
|
||
|
ldr tmp2, .saved_mck3
|
||
|
b r_ps
|
||
|
|
||
|
r_save_mck4:
|
||
|
ldr tmp2, .saved_mck4
|
||
|
|
||
|
r_ps:
|
||
|
/* Write MCK ID to retrieve the settings. */
|
||
|
str tmp1, [pmc, #AT91_PMC_MCR_V2]
|
||
|
ldr tmp3, [pmc, #AT91_PMC_MCR_V2]
|
||
|
|
||
|
/* We need to restore CSS and DIV. */
|
||
|
bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS
|
||
|
bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV
|
||
|
orr tmp3, tmp3, tmp2
|
||
|
bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MSK
|
||
|
orr tmp3, tmp3, tmp1
|
||
|
orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
|
||
|
str tmp2, [pmc, #AT91_PMC_MCR_V2]
|
||
|
|
||
|
wait_mckrdy tmp1
|
||
|
|
||
|
add tmp1, tmp1, #1
|
||
|
b r_loop
|
||
|
r_done:
|
||
|
#endif
|
||
|
.endm
|
||
|
|
||
|
.macro at91_ulp_mode
|
||
|
at91_mckx_ps_enable
|
||
|
|
||
|
ldr pmc, .pmc_base
|
||
|
ldr tmp2, .mckr_offset
|
||
|
ldr tmp3, .pm_mode
|
||
|
|
||
|
/* Save Master clock setting */
|
||
|
ldr tmp1, [pmc, tmp2]
|
||
|
str tmp1, .saved_mckr
|
||
|
|
||
|
/*
|
||
|
* Set master clock source to:
|
||
|
* - MAINCK if using ULP0 fast variant
|
||
|
* - slow clock, otherwise
|
||
|
*/
|
||
|
bic tmp1, tmp1, #AT91_PMC_CSS
|
||
|
cmp tmp3, #AT91_PM_ULP0_FAST
|
||
|
bne save_mck
|
||
|
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
|
||
|
save_mck:
|
||
|
str tmp1, [pmc, tmp2]
|
||
|
|
||
|
mov tmp3, #0
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
at91_plla_disable
|
||
|
|
||
|
/* Enable low power mode for 2.5V regulator. */
|
||
|
at91_2_5V_reg_set_low_power 1
|
||
|
|
||
|
ldr tmp3, .pm_mode
|
||
|
cmp tmp3, #AT91_PM_ULP1
|
||
|
beq ulp1_mode
|
||
|
|
||
|
at91_pm_ulp0_mode
|
||
|
b ulp_exit
|
||
|
|
||
|
ulp1_mode:
|
||
|
at91_pm_ulp1_mode
|
||
|
b ulp_exit
|
||
|
|
||
|
ulp_exit:
|
||
|
/* Disable low power mode for 2.5V regulator. */
|
||
|
at91_2_5V_reg_set_low_power 0
|
||
|
|
||
|
ldr pmc, .pmc_base
|
||
|
|
||
|
at91_plla_enable
|
||
|
|
||
|
/*
|
||
|
* Restore master clock setting
|
||
|
*/
|
||
|
ldr tmp1, .mckr_offset
|
||
|
ldr tmp2, .saved_mckr
|
||
|
str tmp2, [pmc, tmp1]
|
||
|
|
||
|
mov tmp3, #0
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
at91_mckx_ps_restore
|
||
|
.endm
|
||
|
|
||
|
.macro at91_backup_mode
|
||
|
/* Switch the master clock source to slow clock. */
|
||
|
ldr pmc, .pmc_base
|
||
|
ldr tmp2, .mckr_offset
|
||
|
ldr tmp1, [pmc, tmp2]
|
||
|
bic tmp1, tmp1, #AT91_PMC_CSS
|
||
|
str tmp1, [pmc, tmp2]
|
||
|
|
||
|
mov tmp3, #0
|
||
|
wait_mckrdy tmp3
|
||
|
|
||
|
/*BUMEN*/
|
||
|
ldr r0, .sfrbu
|
||
|
mov tmp1, #0x1
|
||
|
str tmp1, [r0, #0x10]
|
||
|
|
||
|
/* Wait for it. */
|
||
|
1: ldr tmp1, [r0, #0x10]
|
||
|
tst tmp1, #0x1
|
||
|
beq 1b
|
||
|
|
||
|
/* Shutdown */
|
||
|
ldr r0, .shdwc
|
||
|
mov tmp1, #0xA5000000
|
||
|
add tmp1, tmp1, #0x1
|
||
|
at91_backup_set_lpm tmp1
|
||
|
str tmp1, [r0, #0]
|
||
|
.endm
|
||
|
|
||
|
/*
|
||
|
* void at91_suspend_sram_fn(struct at91_pm_data*)
|
||
|
* @input param:
|
||
|
* @r0: base address of struct at91_pm_data
|
||
|
*/
|
||
|
/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
|
||
|
.align 3
|
||
|
ENTRY(at91_pm_suspend_in_sram)
|
||
|
/* Save registers on stack */
|
||
|
stmfd sp!, {r4 - r12, lr}
|
||
|
|
||
|
/* Drain write buffer */
|
||
|
mov tmp1, #0
|
||
|
mcr p15, 0, tmp1, c7, c10, 4
|
||
|
|
||
|
/* Flush tlb. */
|
||
|
mov r4, #0
|
||
|
mcr p15, 0, r4, c8, c7, 0
|
||
|
|
||
|
ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
|
||
|
str tmp1, .mckr_offset
|
||
|
ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
|
||
|
str tmp1, .pmc_version
|
||
|
ldr tmp1, [r0, #PM_DATA_MEMCTRL]
|
||
|
str tmp1, .memtype
|
||
|
ldr tmp1, [r0, #PM_DATA_MODE]
|
||
|
str tmp1, .pm_mode
|
||
|
|
||
|
/*
|
||
|
* ldrne below are here to preload their address in the TLB as access
|
||
|
* to RAM may be limited while in self-refresh.
|
||
|
*/
|
||
|
ldr tmp1, [r0, #PM_DATA_PMC]
|
||
|
str tmp1, .pmc_base
|
||
|
cmp tmp1, #0
|
||
|
ldrne tmp2, [tmp1, #0]
|
||
|
|
||
|
ldr tmp1, [r0, #PM_DATA_RAMC0]
|
||
|
str tmp1, .sramc_base
|
||
|
cmp tmp1, #0
|
||
|
ldrne tmp2, [tmp1, #0]
|
||
|
|
||
|
ldr tmp1, [r0, #PM_DATA_RAMC1]
|
||
|
str tmp1, .sramc1_base
|
||
|
cmp tmp1, #0
|
||
|
ldrne tmp2, [tmp1, #0]
|
||
|
|
||
|
#ifndef CONFIG_SOC_SAM_V4_V5
|
||
|
/* ldrne below are here to preload their address in the TLB */
|
||
|
ldr tmp1, [r0, #PM_DATA_RAMC_PHY]
|
||
|
str tmp1, .sramc_phy_base
|
||
|
cmp tmp1, #0
|
||
|
ldrne tmp2, [tmp1, #0]
|
||
|
|
||
|
ldr tmp1, [r0, #PM_DATA_SHDWC]
|
||
|
str tmp1, .shdwc
|
||
|
cmp tmp1, #0
|
||
|
ldrne tmp2, [tmp1, #0]
|
||
|
|
||
|
ldr tmp1, [r0, #PM_DATA_SFRBU]
|
||
|
str tmp1, .sfrbu
|
||
|
cmp tmp1, #0
|
||
|
ldrne tmp2, [tmp1, #0x10]
|
||
|
#endif
|
||
|
|
||
|
/* Active the self-refresh mode */
|
||
|
at91_sramc_self_refresh_ena
|
||
|
|
||
|
ldr r0, .pm_mode
|
||
|
cmp r0, #AT91_PM_STANDBY
|
||
|
beq standby
|
||
|
cmp r0, #AT91_PM_BACKUP
|
||
|
beq backup_mode
|
||
|
|
||
|
at91_ulp_mode
|
||
|
b exit_suspend
|
||
|
|
||
|
standby:
|
||
|
/* Wait for interrupt */
|
||
|
ldr pmc, .pmc_base
|
||
|
at91_cpu_idle
|
||
|
b exit_suspend
|
||
|
|
||
|
backup_mode:
|
||
|
at91_backup_mode
|
||
|
|
||
|
exit_suspend:
|
||
|
/* Exit the self-refresh mode */
|
||
|
at91_sramc_self_refresh_dis
|
||
|
|
||
|
/* Restore registers, and return */
|
||
|
ldmfd sp!, {r4 - r12, pc}
|
||
|
ENDPROC(at91_pm_suspend_in_sram)
|
||
|
|
||
|
.pmc_base:
|
||
|
.word 0
|
||
|
.sramc_base:
|
||
|
.word 0
|
||
|
.sramc1_base:
|
||
|
.word 0
|
||
|
.sramc_phy_base:
|
||
|
.word 0
|
||
|
.shdwc:
|
||
|
.word 0
|
||
|
.sfrbu:
|
||
|
.word 0
|
||
|
.memtype:
|
||
|
.word 0
|
||
|
.pm_mode:
|
||
|
.word 0
|
||
|
.mckr_offset:
|
||
|
.word 0
|
||
|
.pmc_version:
|
||
|
.word 0
|
||
|
.saved_mckr:
|
||
|
.word 0
|
||
|
.saved_pllar:
|
||
|
.word 0
|
||
|
.saved_sam9_lpr:
|
||
|
.word 0
|
||
|
.saved_sam9_lpr1:
|
||
|
.word 0
|
||
|
.saved_sam9_mdr:
|
||
|
.word 0
|
||
|
.saved_sam9_mdr1:
|
||
|
.word 0
|
||
|
.saved_osc_status:
|
||
|
.word 0
|
||
|
#ifdef CONFIG_SOC_SAMA7
|
||
|
.saved_mck1:
|
||
|
.word 0
|
||
|
.saved_mck2:
|
||
|
.word 0
|
||
|
.saved_mck3:
|
||
|
.word 0
|
||
|
.saved_mck4:
|
||
|
.word 0
|
||
|
#endif
|
||
|
|
||
|
ENTRY(at91_pm_suspend_in_sram_sz)
|
||
|
.word .-at91_pm_suspend_in_sram
|