xref: /OK3568_Linux_fs/kernel/arch/arm/mach-omap2/sleep24xx.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun/*
3*4882a593Smuzhiyun * linux/arch/arm/mach-omap2/sleep.S
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright 2004
6*4882a593Smuzhiyun * Texas Instruments, <www.ti.com>
7*4882a593Smuzhiyun * Richard Woodruff <r-woodruff2@ti.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * (C) Copyright 2006 Nokia Corporation
10*4882a593Smuzhiyun * Fixed idle loop sleep
11*4882a593Smuzhiyun * Igor Stoppa <igor.stoppa@nokia.com>
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun#include <linux/linkage.h>
15*4882a593Smuzhiyun#include <asm/assembler.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun#include "omap24xx.h"
18*4882a593Smuzhiyun#include "sdrc.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun/* First address of reserved address space?  apparently valid for OMAP2 & 3 */
21*4882a593Smuzhiyun#define A_SDRC0_V		(0xC0000000)
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun	.text
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun/*
26*4882a593Smuzhiyun * omap24xx_cpu_suspend() - Forces OMAP into deep sleep state by completing
27*4882a593Smuzhiyun * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
28*4882a593Smuzhiyun * SDRC.
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun * Input:
31*4882a593Smuzhiyun * R0 :	DLL ctrl value pre-Sleep
32*4882a593Smuzhiyun * R1 : SDRC_DLLA_CTRL
33*4882a593Smuzhiyun * R2 : SDRC_POWER
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
36*4882a593Smuzhiyun * when we get called, but the DLL probably isn't.  We will wait a bit more in
37*4882a593Smuzhiyun * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
38*4882a593Smuzhiyun * if in unlocked mode.
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * For less than 242x-ES2.2 upon wake from a sleep mode where the external
41*4882a593Smuzhiyun * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
42*4882a593Smuzhiyun * clock can pass into the PRCM can cause problems at DSP and IVA.
43*4882a593Smuzhiyun * To work around this the code will switch to the 32kHz source prior to sleep.
44*4882a593Smuzhiyun * Post sleep we will shift back to using the DPLL.  Apparently,
45*4882a593Smuzhiyun * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
46*4882a593Smuzhiyun * 3x12MHz + 3x32kHz clocks for a full switch.
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * The DLL load value is not kept in RETENTION or OFF.	It needs to be restored
49*4882a593Smuzhiyun * at wake
50*4882a593Smuzhiyun */
51*4882a593Smuzhiyun	.align	3
52*4882a593SmuzhiyunENTRY(omap24xx_cpu_suspend)
53*4882a593Smuzhiyun	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
54*4882a593Smuzhiyun	mov	r3, #0x0		@ clear for mcr call
55*4882a593Smuzhiyun	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier, hope SDR/DDR finished
56*4882a593Smuzhiyun	nop
57*4882a593Smuzhiyun	nop
58*4882a593Smuzhiyun	ldr	r4, [r2]		@ read SDRC_POWER
59*4882a593Smuzhiyun	orr	r4, r4, #0x40		@ enable self refresh on idle req
60*4882a593Smuzhiyun	mov	r5, #0x2000		@ set delay (DPLL relock + DLL relock)
61*4882a593Smuzhiyun	str	r4, [r2]		@ make it so
62*4882a593Smuzhiyun	nop
63*4882a593Smuzhiyun	mcr	p15, 0, r3, c7, c0, 4	@ wait for interrupt
64*4882a593Smuzhiyun	nop
65*4882a593Smuzhiyunloop:
66*4882a593Smuzhiyun	subs	r5, r5, #0x1		@ awake, wait just a bit
67*4882a593Smuzhiyun	bne	loop
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun	/* The DPLL has to be on before we take the DDR out of self refresh */
70*4882a593Smuzhiyun	bic	r4, r4, #0x40		@ now clear self refresh bit.
71*4882a593Smuzhiyun	str	r4, [r2]		@ write to SDRC_POWER
72*4882a593Smuzhiyun	ldr	r4, A_SDRC0		@ make a clock happen
73*4882a593Smuzhiyun	ldr	r4, [r4]		@ read A_SDRC0
74*4882a593Smuzhiyun	nop				@ start auto refresh only after clk ok
75*4882a593Smuzhiyun	movs	r0, r0			@ see if DDR or SDR
76*4882a593Smuzhiyun	strne	r0, [r1]		@ rewrite DLLA to force DLL reload
77*4882a593Smuzhiyun	addne	r1, r1, #0x8		@ move to DLLB
78*4882a593Smuzhiyun	strne	r0, [r1]		@ rewrite DLLB to force DLL reload
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun	mov	r5, #0x1000
81*4882a593Smuzhiyunloop2:
82*4882a593Smuzhiyun	subs	r5, r5, #0x1
83*4882a593Smuzhiyun	bne	loop2
84*4882a593Smuzhiyun	/* resume*/
85*4882a593Smuzhiyun	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return
86*4882a593Smuzhiyun
87*4882a593SmuzhiyunA_SDRC0:
88*4882a593Smuzhiyun	.word A_SDRC0_V
89*4882a593Smuzhiyun
90*4882a593SmuzhiyunENTRY(omap24xx_cpu_suspend_sz)
91*4882a593Smuzhiyun	.word	. - omap24xx_cpu_suspend
92