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