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