1/*
2 * arch/arm/mach-at91/pm_slow_clock.S
3 *
4 *  Copyright (C) 2006 Savin Zlobec
5 *
6 * AT91SAM9 support:
7 *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/linkage.h>
16#include <mach/hardware.h>
17#include <mach/at91_pmc.h>
18
19#if defined(CONFIG_ARCH_AT91RM9200)
20#include <mach/at91rm9200_mc.h>
21#elif defined(CONFIG_ARCH_AT91CAP9) \
22	|| defined(CONFIG_ARCH_AT91SAM9G45)
23#include <mach/at91sam9_ddrsdr.h>
24#else
25#include <mach/at91sam9_sdramc.h>
26#endif
27
28
29#ifdef CONFIG_ARCH_AT91SAM9263
30/*
31 * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
32 * handle those cases both here and in the Suspend-To-RAM support.
33 */
34#warning Assuming EB1 SDRAM controller is *NOT* used
35#endif
36
37/*
38 * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
39 * clock during suspend by adjusting its prescalar and divisor.
40 * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
41 *       are errata regarding adjusting the prescalar and divisor.
42 */
43#undef SLOWDOWN_MASTER_CLOCK
44
45#define MCKRDY_TIMEOUT		1000
46#define MOSCRDY_TIMEOUT 	1000
47#define PLLALOCK_TIMEOUT	1000
48#define PLLBLOCK_TIMEOUT	1000
49
50
51/*
52 * Wait until master clock is ready (after switching master clock source)
53 */
54	.macro wait_mckrdy
55	mov	r4, #MCKRDY_TIMEOUT
561:	sub	r4, r4, #1
57	cmp	r4, #0
58	beq	2f
59	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
60	tst	r3, #AT91_PMC_MCKRDY
61	beq	1b
622:
63	.endm
64
65/*
66 * Wait until master oscillator has stabilized.
67 */
68	.macro wait_moscrdy
69	mov	r4, #MOSCRDY_TIMEOUT
701:	sub	r4, r4, #1
71	cmp	r4, #0
72	beq	2f
73	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
74	tst	r3, #AT91_PMC_MOSCS
75	beq	1b
762:
77	.endm
78
79/*
80 * Wait until PLLA has locked.
81 */
82	.macro wait_pllalock
83	mov	r4, #PLLALOCK_TIMEOUT
841:	sub	r4, r4, #1
85	cmp	r4, #0
86	beq	2f
87	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
88	tst	r3, #AT91_PMC_LOCKA
89	beq	1b
902:
91	.endm
92
93/*
94 * Wait until PLLB has locked.
95 */
96	.macro wait_pllblock
97	mov	r4, #PLLBLOCK_TIMEOUT
981:	sub	r4, r4, #1
99	cmp	r4, #0
100	beq	2f
101	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
102	tst	r3, #AT91_PMC_LOCKB
103	beq	1b
1042:
105	.endm
106
107	.text
108
109ENTRY(at91_slow_clock)
110	/* Save registers on stack */
111	stmfd	sp!, {r0 - r12, lr}
112
113	/*
114	 * Register usage:
115	 *  R1 = Base address of AT91_PMC
116	 *  R2 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
117	 *  R3 = temporary register
118	 *  R4 = temporary register
119	 *  R5 = Base address of second RAM Controller or 0 if not present
120	 */
121	ldr	r1, .at91_va_base_pmc
122	ldr	r2, .at91_va_base_sdramc
123	ldr	r5, .at91_va_base_ramc1
124
125	/* Drain write buffer */
126	mov	r0, #0
127	mcr	p15, 0, r0, c7, c10, 4
128
129#ifdef CONFIG_ARCH_AT91RM9200
130	/* Put SDRAM in self-refresh mode */
131	mov	r3, #1
132	str	r3, [r2, #AT91_SDRAMC_SRR]
133#elif defined(CONFIG_ARCH_AT91CAP9) \
134	|| defined(CONFIG_ARCH_AT91SAM9G45)
135
136	/* prepare for DDRAM self-refresh mode */
137	ldr	r3, [r2, #AT91_DDRSDRC_LPR]
138	str	r3, .saved_sam9_lpr
139	bic	r3, #AT91_DDRSDRC_LPCB
140	orr	r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
141
142	/* figure out if we use the second ram controller */
143	cmp	r5, #0
144	ldrne	r4, [r5, #AT91_DDRSDRC_LPR]
145	strne	r4, .saved_sam9_lpr1
146	bicne	r4, #AT91_DDRSDRC_LPCB
147	orrne	r4, #AT91_DDRSDRC_LPCB_SELF_REFRESH
148
149	/* Enable DDRAM self-refresh mode */
150	str	r3, [r2, #AT91_DDRSDRC_LPR]
151	strne	r4, [r5, #AT91_DDRSDRC_LPR]
152#else
153	/* Enable SDRAM self-refresh mode */
154	ldr	r3, [r2, #AT91_SDRAMC_LPR]
155	str	r3, .saved_sam9_lpr
156
157	bic	r3, #AT91_SDRAMC_LPCB
158	orr	r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
159	str	r3, [r2, #AT91_SDRAMC_LPR]
160#endif
161
162	/* Save Master clock setting */
163	ldr	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
164	str	r3, .saved_mckr
165
166	/*
167	 * Set the Master clock source to slow clock
168	 */
169	bic	r3, r3, #AT91_PMC_CSS
170	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
171
172	wait_mckrdy
173
174#ifdef SLOWDOWN_MASTER_CLOCK
175	/*
176	 * Set the Master Clock PRES and MDIV fields.
177	 *
178	 * See AT91RM9200 errata #27 and #28 for details.
179	 */
180	mov	r3, #0
181	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
182
183	wait_mckrdy
184#endif
185
186	/* Save PLLA setting and disable it */
187	ldr	r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
188	str	r3, .saved_pllar
189
190	mov	r3, #AT91_PMC_PLLCOUNT
191	orr	r3, r3, #(1 << 29)		/* bit 29 always set */
192	str	r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
193
194	/* Save PLLB setting and disable it */
195	ldr	r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
196	str	r3, .saved_pllbr
197
198	mov	r3, #AT91_PMC_PLLCOUNT
199	str	r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
200
201	/* Turn off the main oscillator */
202	ldr	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
203	bic	r3, r3, #AT91_PMC_MOSCEN
204	str	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
205
206	/* Wait for interrupt */
207	mcr	p15, 0, r0, c7, c0, 4
208
209	/* Turn on the main oscillator */
210	ldr	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
211	orr	r3, r3, #AT91_PMC_MOSCEN
212	str	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
213
214	wait_moscrdy
215
216	/* Restore PLLB setting */
217	ldr	r3, .saved_pllbr
218	str	r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
219
220	tst	r3, #(AT91_PMC_MUL &  0xff0000)
221	bne	1f
222	tst	r3, #(AT91_PMC_MUL & ~0xff0000)
223	beq	2f
2241:
225	wait_pllblock
2262:
227
228	/* Restore PLLA setting */
229	ldr	r3, .saved_pllar
230	str	r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
231
232	tst	r3, #(AT91_PMC_MUL &  0xff0000)
233	bne	3f
234	tst	r3, #(AT91_PMC_MUL & ~0xff0000)
235	beq	4f
2363:
237	wait_pllalock
2384:
239
240#ifdef SLOWDOWN_MASTER_CLOCK
241	/*
242	 * First set PRES if it was not 0,
243	 * than set CSS and MDIV fields.
244	 *
245	 * See AT91RM9200 errata #27 and #28 for details.
246	 */
247	ldr	r3, .saved_mckr
248	tst	r3, #AT91_PMC_PRES
249	beq	2f
250	and	r3, r3, #AT91_PMC_PRES
251	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
252
253	wait_mckrdy
254#endif
255
256	/*
257	 * Restore master clock setting
258	 */
2592:	ldr	r3, .saved_mckr
260	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
261
262	wait_mckrdy
263
264#ifdef CONFIG_ARCH_AT91RM9200
265	/* Do nothing - self-refresh is automatically disabled. */
266#elif defined(CONFIG_ARCH_AT91CAP9) \
267	|| defined(CONFIG_ARCH_AT91SAM9G45)
268	/* Restore LPR on AT91 with DDRAM */
269	ldr	r3, .saved_sam9_lpr
270	str	r3, [r2, #AT91_DDRSDRC_LPR]
271
272	/* if we use the second ram controller */
273	cmp	r5, #0
274	ldrne	r4, .saved_sam9_lpr1
275	strne	r4, [r5, #AT91_DDRSDRC_LPR]
276
277#else
278	/* Restore LPR on AT91 with SDRAM */
279	ldr	r3, .saved_sam9_lpr
280	str	r3, [r2, #AT91_SDRAMC_LPR]
281#endif
282
283	/* Restore registers, and return */
284	ldmfd	sp!, {r0 - r12, pc}
285
286
287.saved_mckr:
288	.word 0
289
290.saved_pllar:
291	.word 0
292
293.saved_pllbr:
294	.word 0
295
296.saved_sam9_lpr:
297	.word 0
298
299.saved_sam9_lpr1:
300	.word 0
301
302.at91_va_base_pmc:
303	.word AT91_VA_BASE_SYS + AT91_PMC
304
305#ifdef CONFIG_ARCH_AT91RM9200
306.at91_va_base_sdramc:
307	.word AT91_VA_BASE_SYS
308#elif defined(CONFIG_ARCH_AT91CAP9) \
309	|| defined(CONFIG_ARCH_AT91SAM9G45)
310.at91_va_base_sdramc:
311	.word AT91_VA_BASE_SYS + AT91_DDRSDRC0
312#else
313.at91_va_base_sdramc:
314	.word AT91_VA_BASE_SYS + AT91_SDRAMC0
315#endif
316
317.at91_va_base_ramc1:
318#if defined(CONFIG_ARCH_AT91SAM9G45)
319	.word AT91_VA_BASE_SYS + AT91_DDRSDRC1
320#else
321	.word 0
322#endif
323
324ENTRY(at91_slow_clock_sz)
325	.word .-at91_slow_clock
326