1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * (C) Copyright 2009, Texas Instruments, Inc. https://www.ti.com/
4  */
5 
6 /* replicated define because linux/bitops.h cannot be included in assembly */
7 #define BIT(nr)			(1 << (nr))
8 
9 #include <linux/linkage.h>
10 #include <asm/assembler.h>
11 #include "psc.h"
12 #include "ddr2.h"
13 
14 #include "clock.h"
15 
16 /* Arbitrary, hardware currently does not update PHYRDY correctly */
17 #define PHYRDY_CYCLES		0x1000
18 
19 /* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
20 #define PLL_BYPASS_CYCLES	(PLL_BYPASS_TIME * 25)
21 #define PLL_RESET_CYCLES	(PLL_RESET_TIME	* 25)
22 #define PLL_LOCK_CYCLES		(PLL_LOCK_TIME * 25)
23 
24 #define DEEPSLEEP_SLEEPENABLE_BIT	BIT(31)
25 
26 	.text
27 	.arch	armv5te
28 /*
29  * Move DaVinci into deep sleep state
30  *
31  * Note: This code is copied to internal SRAM by PM code. When the DaVinci
32  *	 wakes up it continues execution at the point it went to sleep.
33  * Register Usage:
34  * 	r0: contains virtual base for DDR2 controller
35  * 	r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
36  * 	r2: contains PSC number for DDR2
37  * 	r3: contains virtual base DDR2 PLL controller
38  * 	r4: contains virtual address of the DEEPSLEEP register
39  */
40 ENTRY(davinci_cpu_suspend)
41 	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
42 
43 	ldr 	ip, CACHE_FLUSH
44 	blx	ip
45 
46 	ldmia	r0, {r0-r4}
47 
48 	/*
49 	 * Switch DDR to self-refresh mode.
50 	 */
51 
52 	/* calculate SDRCR address */
53 	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
54 	bic	ip, ip, #DDR2_SRPD_BIT
55 	orr	ip, ip, #DDR2_LPMODEN_BIT
56 	str	ip, [r0, #DDR2_SDRCR_OFFSET]
57 
58 	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
59 	orr	ip, ip, #DDR2_MCLKSTOPEN_BIT
60 	str	ip, [r0, #DDR2_SDRCR_OFFSET]
61 
62        mov	ip, #PHYRDY_CYCLES
63 1:     subs	ip, ip, #0x1
64        bne	1b
65 
66        /* Disable DDR2 LPSC */
67 	mov	r7, r0
68 	mov	r0, #0x2
69 	bl davinci_ddr_psc_config
70 	mov	r0, r7
71 
72 	/* Disable clock to DDR PHY */
73 	ldr	ip, [r3, #PLLDIV1]
74 	bic	ip, ip, #PLLDIV_EN
75 	str	ip, [r3, #PLLDIV1]
76 
77 	/* Put the DDR PLL in bypass and power down */
78 	ldr	ip, [r3, #PLLCTL]
79 	bic	ip, ip, #PLLCTL_PLLENSRC
80 	bic	ip, ip, #PLLCTL_PLLEN
81 	str	ip, [r3, #PLLCTL]
82 
83 	/* Wait for PLL to switch to bypass */
84        mov	ip, #PLL_BYPASS_CYCLES
85 2:     subs	ip, ip, #0x1
86        bne	2b
87 
88        /* Power down the PLL */
89 	ldr	ip, [r3, #PLLCTL]
90 	orr	ip, ip, #PLLCTL_PLLPWRDN
91 	str	ip, [r3, #PLLCTL]
92 
93 	/* Go to deep sleep */
94 	ldr	ip, [r4]
95 	orr	ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
96 	/* System goes to sleep beyond after this instruction */
97 	str	ip, [r4]
98 
99 	/* Wake up from sleep */
100 
101 	/* Clear sleep enable */
102 	ldr	ip, [r4]
103 	bic	ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
104 	str	ip, [r4]
105 
106 	/* initialize the DDR PLL controller */
107 
108 	/* Put PLL in reset */
109 	ldr	ip, [r3, #PLLCTL]
110 	bic	ip, ip, #PLLCTL_PLLRST
111 	str	ip, [r3, #PLLCTL]
112 
113 	/* Clear PLL power down */
114 	ldr	ip, [r3, #PLLCTL]
115 	bic	ip, ip, #PLLCTL_PLLPWRDN
116 	str	ip, [r3, #PLLCTL]
117 
118        mov	ip, #PLL_RESET_CYCLES
119 3:     subs	ip, ip, #0x1
120        bne	3b
121 
122        /* Bring PLL out of reset */
123 	ldr	ip, [r3, #PLLCTL]
124 	orr	ip, ip, #PLLCTL_PLLRST
125 	str	ip, [r3, #PLLCTL]
126 
127 	/* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
128        mov	ip, #PLL_LOCK_CYCLES
129 4:     subs	ip, ip, #0x1
130        bne	4b
131 
132        /* Remove PLL from bypass mode */
133 	ldr	ip, [r3, #PLLCTL]
134 	bic	ip, ip, #PLLCTL_PLLENSRC
135 	orr	ip, ip, #PLLCTL_PLLEN
136 	str	ip, [r3, #PLLCTL]
137 
138 	/* Start 2x clock to DDR2 */
139 
140 	ldr	ip, [r3, #PLLDIV1]
141 	orr	ip, ip, #PLLDIV_EN
142 	str	ip, [r3, #PLLDIV1]
143 
144 	/* Enable VCLK */
145 
146        /* Enable DDR2 LPSC */
147 	mov	r7, r0
148 	mov	r0, #0x3
149 	bl davinci_ddr_psc_config
150 	mov	r0, r7
151 
152 	/* clear  MCLKSTOPEN */
153 
154 	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
155 	bic	ip, ip, #DDR2_MCLKSTOPEN_BIT
156 	str	ip, [r0, #DDR2_SDRCR_OFFSET]
157 
158 	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
159 	bic	ip, ip, #DDR2_LPMODEN_BIT
160 	str	ip, [r0, #DDR2_SDRCR_OFFSET]
161 
162 	/* Restore registers and return */
163 	ldmfd   sp!, {r0-r12, pc}
164 
165 ENDPROC(davinci_cpu_suspend)
166 
167 /*
168  * Disables or Enables DDR2 LPSC
169  * Register Usage:
170  * 	r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
171  * 	r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
172  * 	r2: contains PSC number for DDR2
173  */
174 ENTRY(davinci_ddr_psc_config)
175 	/* Set next state in mdctl for DDR2 */
176 	mov	r6, #MDCTL
177 	add	r6, r6, r2, lsl #2
178 	ldr	ip, [r1, r6]
179 	bic	ip, ip, #MDSTAT_STATE_MASK
180 	orr	ip, ip, r0
181 	str	ip, [r1, r6]
182 
183 	/* Enable the Power Domain Transition Command */
184 	ldr	ip, [r1, #PTCMD]
185 	orr	ip, ip, #0x1
186 	str	ip, [r1, #PTCMD]
187 
188 	/* Check for Transition Complete (PTSTAT) */
189 ptstat_done:
190 	ldr	ip, [r1, #PTSTAT]
191 	and	ip, ip, #0x1
192 	cmp 	ip, #0x0
193 	bne	ptstat_done
194 
195 	/* Check for DDR2 clock disable completion; */
196 	mov	r6, #MDSTAT
197 	add	r6, r6, r2, lsl #2
198 ddr2clk_stop_done:
199 	ldr	ip, [r1, r6]
200 	and	ip, ip, #MDSTAT_STATE_MASK
201 	cmp	ip, r0
202 	bne	ddr2clk_stop_done
203 
204 	ret	lr
205 ENDPROC(davinci_ddr_psc_config)
206 
207 CACHE_FLUSH:
208 #ifdef CONFIG_CPU_V6
209 	.word	v6_flush_kern_cache_all
210 #else
211 	.word   arm926_flush_kern_cache_all
212 #endif
213 
214 ENTRY(davinci_cpu_suspend_sz)
215 	.word	. - davinci_cpu_suspend
216 ENDPROC(davinci_cpu_suspend_sz)
217