| /* 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_PWRCTRL_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 | 
 |  | 
 | 	/* Disable DX DLLs for non-backup modes. */ | 
 | 	cmp	r7, #AT91_PM_BACKUP | 
 | 	beq	sr_ena_3 | 
 |  | 
 | 	/* Do not soft reset the AC DLL. */ | 
 | 	ldr	tmp1, [r3, DDR3PHY_ACDLLCR] | 
 | 	bic	tmp1, tmp1, DDR3PHY_ACDLLCR_DLLSRST | 
 | 	str	tmp1, [r3, DDR3PHY_ACDLLCR] | 
 |  | 
 | 	/* Disable DX DLLs. */ | 
 | 	ldr	tmp1, [r3, #DDR3PHY_DX0DLLCR] | 
 | 	orr	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS | 
 | 	str	tmp1, [r3, #DDR3PHY_DX0DLLCR] | 
 |  | 
 | 	ldr	tmp1, [r3, #DDR3PHY_DX1DLLCR] | 
 | 	orr	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS | 
 | 	str	tmp1, [r3, #DDR3PHY_DX1DLLCR] | 
 |  | 
 | 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] | 
 |  | 
 | 	/* Enable DX DLLs. */ | 
 | 	ldr	tmp1, [r3, #DDR3PHY_DX0DLLCR] | 
 | 	bic	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS | 
 | 	str	tmp1, [r3, #DDR3PHY_DX0DLLCR] | 
 |  | 
 | 	ldr	tmp1, [r3, #DDR3PHY_DX1DLLCR] | 
 | 	bic	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS | 
 | 	str	tmp1, [r3, #DDR3PHY_DX1DLLCR] | 
 |  | 
 | 	/* 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_PWRCTRL_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 |