pm_slowclock.S 6.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * arch/arm/mach-at91/pm_slow_clock.S
 *
 *  Copyright (C) 2006 Savin Zlobec
 *
 * AT91SAM9 support:
 *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#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 22 23 24 25 26 27 28 29 30 31 32

/*
 * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
 * clock during suspend by adjusting its prescalar and divisor.
 * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
 *       are errata regarding adjusting the prescalar and divisor.
 */
#undef SLOWDOWN_MASTER_CLOCK

#define MCKRDY_TIMEOUT		1000
#define MOSCRDY_TIMEOUT 	1000
#define PLLALOCK_TIMEOUT	1000
#define PLLBLOCK_TIMEOUT	1000

33 34 35
pmc	.req	r0
sdramc	.req	r1
ramc1	.req	r2
36 37 38
memctrl	.req	r3
tmp1	.req	r4
tmp2	.req	r5
39 40 41 42 43

/*
 * Wait until master clock is ready (after switching master clock source)
 */
	.macro wait_mckrdy
44 45 46
	mov	tmp2, #MCKRDY_TIMEOUT
1:	sub	tmp2, tmp2, #1
	cmp	tmp2, #0
47
	beq	2f
48
	ldr	tmp1, [pmc, #AT91_PMC_SR]
49
	tst	tmp1, #AT91_PMC_MCKRDY
50 51 52 53 54 55 56 57
	beq	1b
2:
	.endm

/*
 * Wait until master oscillator has stabilized.
 */
	.macro wait_moscrdy
58 59 60
	mov	tmp2, #MOSCRDY_TIMEOUT
1:	sub	tmp2, tmp2, #1
	cmp	tmp2, #0
61
	beq	2f
62
	ldr	tmp1, [pmc, #AT91_PMC_SR]
63
	tst	tmp1, #AT91_PMC_MOSCS
64 65 66 67 68 69 70 71
	beq	1b
2:
	.endm

/*
 * Wait until PLLA has locked.
 */
	.macro wait_pllalock
72 73 74
	mov	tmp2, #PLLALOCK_TIMEOUT
1:	sub	tmp2, tmp2, #1
	cmp	tmp2, #0
75
	beq	2f
76
	ldr	tmp1, [pmc, #AT91_PMC_SR]
77
	tst	tmp1, #AT91_PMC_LOCKA
78 79 80 81 82 83 84 85
	beq	1b
2:
	.endm

/*
 * Wait until PLLB has locked.
 */
	.macro wait_pllblock
86 87 88
	mov	tmp2, #PLLBLOCK_TIMEOUT
1:	sub	tmp2, tmp2, #1
	cmp	tmp2, #0
89
	beq	2f
90
	ldr	tmp1, [pmc, #AT91_PMC_SR]
91
	tst	tmp1, #AT91_PMC_LOCKB
92 93 94 95 96 97
	beq	1b
2:
	.endm

	.text

98 99 100
/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
 *			void __iomem *ramc1, int memctrl)
 */
101 102
ENTRY(at91_slow_clock)
	/* Save registers on stack */
103
	stmfd	sp!, {r4 - r12, lr}
104 105 106

	/*
	 * Register usage:
107 108 109
	 *  R0 = Base address of AT91_PMC
	 *  R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
	 *  R2 = Base address of second RAM Controller or 0 if not present
110
	 *  R3 = Memory controller
111
	 *  R4 = temporary register
112
	 *  R5 = temporary register
113 114 115
	 */

	/* Drain write buffer */
116 117
	mov	tmp1, #0
	mcr	p15, 0, tmp1, c7, c10, 4
118

119 120 121 122 123 124
	cmp	memctrl, #AT91_MEMCTRL_MC
	bne	ddr_sr_enable

	/*
	 * at91rm9200 Memory controller
	 */
125
	/* Put SDRAM in self-refresh mode */
126
	mov	tmp1, #1
127
	str	tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
128 129 130 131 132 133 134 135
	b	sdr_sr_done

	/*
	 * DDRSDR Memory controller
	 */
ddr_sr_enable:
	cmp	memctrl, #AT91_MEMCTRL_DDRSDR
	bne	sdr_sr_enable
136

137
	/* prepare for DDRAM self-refresh mode */
138 139 140 141
	ldr	tmp1, [sdramc, #AT91_DDRSDRC_LPR]
	str	tmp1, .saved_sam9_lpr
	bic	tmp1, #AT91_DDRSDRC_LPCB
	orr	tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
142 143

	/* figure out if we use the second ram controller */
144 145 146 147 148
	cmp	ramc1, #0
	ldrne	tmp2, [ramc1, #AT91_DDRSDRC_LPR]
	strne	tmp2, .saved_sam9_lpr1
	bicne	tmp2, #AT91_DDRSDRC_LPCB
	orrne	tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
149 150

	/* Enable DDRAM self-refresh mode */
151 152
	str	tmp1, [sdramc, #AT91_DDRSDRC_LPR]
	strne	tmp2, [ramc1, #AT91_DDRSDRC_LPR]
153 154 155 156 157 158 159

	b	sdr_sr_done

	/*
	 * SDRAMC Memory controller
	 */
sdr_sr_enable:
160
	/* Enable SDRAM self-refresh mode */
161 162
	ldr	tmp1, [sdramc, #AT91_SDRAMC_LPR]
	str	tmp1, .saved_sam9_lpr
163

164 165 166
	bic	tmp1, #AT91_SDRAMC_LPCB
	orr	tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
	str	tmp1, [sdramc, #AT91_SDRAMC_LPR]
167

168
sdr_sr_done:
169
	/* Save Master clock setting */
170
	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
171
	str	tmp1, .saved_mckr
172 173 174 175

	/*
	 * Set the Master clock source to slow clock
	 */
176
	bic	tmp1, tmp1, #AT91_PMC_CSS
177
	str	tmp1, [pmc, #AT91_PMC_MCKR]
178 179 180 181 182 183 184 185 186

	wait_mckrdy

#ifdef SLOWDOWN_MASTER_CLOCK
	/*
	 * Set the Master Clock PRES and MDIV fields.
	 *
	 * See AT91RM9200 errata #27 and #28 for details.
	 */
187
	mov	tmp1, #0
188
	str	tmp1, [pmc, #AT91_PMC_MCKR]
189 190 191 192 193

	wait_mckrdy
#endif

	/* Save PLLA setting and disable it */
194
	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
195
	str	tmp1, .saved_pllar
196

197 198
	mov	tmp1, #AT91_PMC_PLLCOUNT
	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
199
	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
200 201

	/* Save PLLB setting and disable it */
202
	ldr	tmp1, [pmc, #AT91_CKGR_PLLBR]
203
	str	tmp1, .saved_pllbr
204

205
	mov	tmp1, #AT91_PMC_PLLCOUNT
206
	str	tmp1, [pmc, #AT91_CKGR_PLLBR]
207 208

	/* Turn off the main oscillator */
209
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
210
	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
211
	str	tmp1, [pmc, #AT91_CKGR_MOR]
212 213

	/* Wait for interrupt */
214
	mcr	p15, 0, tmp1, c7, c0, 4
215 216

	/* Turn on the main oscillator */
217
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
218
	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
219
	str	tmp1, [pmc, #AT91_CKGR_MOR]
220 221 222 223

	wait_moscrdy

	/* Restore PLLB setting */
224
	ldr	tmp1, .saved_pllbr
225
	str	tmp1, [pmc, #AT91_CKGR_PLLBR]
226

227
	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
228
	bne	1f
229
	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
230 231
	beq	2f
1:
232
	wait_pllblock
233
2:
234 235

	/* Restore PLLA setting */
236
	ldr	tmp1, .saved_pllar
237
	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
238

239
	tst	tmp1, #(AT91_PMC_MUL &  0xff0000)
240
	bne	3f
241
	tst	tmp1, #(AT91_PMC_MUL & ~0xff0000)
242 243
	beq	4f
3:
244
	wait_pllalock
245
4:
246 247 248 249 250 251 252 253

#ifdef SLOWDOWN_MASTER_CLOCK
	/*
	 * First set PRES if it was not 0,
	 * than set CSS and MDIV fields.
	 *
	 * See AT91RM9200 errata #27 and #28 for details.
	 */
254 255
	ldr	tmp1, .saved_mckr
	tst	tmp1, #AT91_PMC_PRES
256
	beq	2f
257
	and	tmp1, tmp1, #AT91_PMC_PRES
258
	str	tmp1, [pmc, #AT91_PMC_MCKR]
259 260 261 262 263 264 265

	wait_mckrdy
#endif

	/*
	 * Restore master clock setting
	 */
266
2:	ldr	tmp1, .saved_mckr
267
	str	tmp1, [pmc, #AT91_PMC_MCKR]
268 269 270

	wait_mckrdy

271 272 273 274 275 276 277 278 279 280 281 282
	/*
	 * at91rm9200 Memory controller
	 * Do nothing - self-refresh is automatically disabled.
	 */
	cmp	memctrl, #AT91_MEMCTRL_MC
	beq	ram_restored

	/*
	 * DDRSDR Memory controller
	 */
	cmp	memctrl, #AT91_MEMCTRL_DDRSDR
	bne	sdr_en_restore
283
	/* Restore LPR on AT91 with DDRAM */
284 285
	ldr	tmp1, .saved_sam9_lpr
	str	tmp1, [sdramc, #AT91_DDRSDRC_LPR]
286 287

	/* if we use the second ram controller */
288 289 290
	cmp	ramc1, #0
	ldrne	tmp2, .saved_sam9_lpr1
	strne	tmp2, [ramc1, #AT91_DDRSDRC_LPR]
291

292 293 294 295 296 297
	b	ram_restored

	/*
	 * SDRAMC Memory controller
	 */
sdr_en_restore:
298
	/* Restore LPR on AT91 with SDRAM */
299 300
	ldr	tmp1, .saved_sam9_lpr
	str	tmp1, [sdramc, #AT91_SDRAMC_LPR]
301

302
ram_restored:
303
	/* Restore registers, and return */
304
	ldmfd	sp!, {r4 - r12, pc}
305 306 307 308 309 310 311 312 313 314 315 316 317 318


.saved_mckr:
	.word 0

.saved_pllar:
	.word 0

.saved_pllbr:
	.word 0

.saved_sam9_lpr:
	.word 0

319 320 321
.saved_sam9_lpr1:
	.word 0

322 323
ENTRY(at91_slow_clock_sz)
	.word .-at91_slow_clock