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