xref: /openbmc/linux/arch/arm/mach-omap2/sram243x.S (revision 384740dc)
1/*
2 * linux/arch/arm/mach-omap2/sram243x.S
3 *
4 * Omap2 specific functions that need to be run in internal SRAM
5 *
6 * (C) Copyright 2004
7 * Texas Instruments, <www.ti.com>
8 * Richard Woodruff <r-woodruff2@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25#include <linux/linkage.h>
26#include <asm/assembler.h>
27#include <mach/io.h>
28#include <mach/hardware.h>
29
30#include "prm.h"
31#include "cm.h"
32#include "sdrc.h"
33
34	.text
35
36ENTRY(omap243x_sram_ddr_init)
37	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
38
39	mov	r12, r2			@ capture CS1 vs CS0
40	mov	r8, r3			@ capture force parameter
41
42	/* frequency shift down */
43	ldr	r2, omap243x_sdi_cm_clksel2_pll	@ get address of dpllout reg
44	mov	r3, #0x1		@ value for 1x operation
45	str	r3, [r2]		@ go to L1-freq operation
46
47	/* voltage shift down */
48	mov r9, #0x1			@ set up for L1 voltage call
49	bl voltage_shift		@ go drop voltage
50
51	/* dll lock mode */
52	ldr	r11, omap243x_sdi_sdrc_dlla_ctrl	@ addr of dlla ctrl
53	ldr	r10, [r11]		@ get current val
54	cmp	r12, #0x1		@ cs1 base (2422 es2.05/1)
55	addeq	r11, r11, #0x8		@ if cs1 base, move to DLLB
56	mvn	r9, #0x4		@ mask to get clear bit2
57	and	r10, r10, r9		@ clear bit2 for lock mode.
58	orr	r10, r10, #0x8		@ make sure DLL on (es2 bit pos)
59	orr	r10, r10, #0x2		@ 90 degree phase for all below 133Mhz
60	str	r10, [r11]		@ commit to DLLA_CTRL
61	bl	i_dll_wait		@ wait for dll to lock
62
63	/* get dll value */
64	add	r11, r11, #0x4		@ get addr of status reg
65	ldr	r10, [r11]		@ get locked value
66
67	/* voltage shift up */
68	mov r9, #0x0			@ shift back to L0-voltage
69	bl voltage_shift		@ go raise voltage
70
71	/* frequency shift up */
72	mov	r3, #0x2		@ value for 2x operation
73	str	r3, [r2]		@ go to L0-freq operation
74
75	/* reset entry mode for dllctrl */
76	sub	r11, r11, #0x4		@ move from status to ctrl
77	cmp	r12, #0x1		@ normalize if cs1 based
78	subeq	r11, r11, #0x8		@ possibly back to DLLA
79	cmp	r8, #0x1		@ if forced unlock exit
80	orreq	r1, r1, #0x4		@ make sure exit with unlocked value
81	str	r1, [r11]		@ restore DLLA_CTRL high value
82	add	r11, r11, #0x8		@ move to DLLB_CTRL addr
83	str	r1, [r11]		@ set value DLLB_CTRL
84	bl	i_dll_wait		@ wait for possible lock
85
86	/* set up for return, DDR should be good */
87	str r10, [r0]			@ write dll_status and return counter
88	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return
89
90	/* ensure the DLL has relocked */
91i_dll_wait:
92	mov	r4, #0x800		@ delay DLL relock, min 0x400 L3 clocks
93i_dll_delay:
94	subs	r4, r4, #0x1
95	bne	i_dll_delay
96	mov	pc, lr
97
98	/*
99	 * shift up or down voltage, use R9 as input to tell level.
100	 * wait for it to finish, use 32k sync counter, 1tick=31uS.
101	 */
102voltage_shift:
103	ldr	r4, omap243x_sdi_prcm_voltctrl	@ get addr of volt ctrl.
104	ldr	r5, [r4]		@ get value.
105	ldr	r6, prcm_mask_val	@ get value of mask
106	and	r5, r5, r6		@ apply mask to clear bits
107	orr	r5, r5, r9		@ bulld value for L0/L1-volt operation.
108	str	r5, [r4]		@ set up for change.
109	mov	r3, #0x4000		@ get val for force
110	orr	r5, r5, r3		@ build value for force
111	str	r5, [r4]		@ Force transition to L1
112
113	ldr	r3, omap243x_sdi_timer_32ksynct_cr	@ get addr of counter
114	ldr	r5, [r3]		@ get value
115	add	r5, r5, #0x3		@ give it at most 93uS
116volt_delay:
117	ldr	r7, [r3]		@ get timer value
118	cmp	r5, r7			@ time up?
119	bhi	volt_delay		@ not yet->branch
120	mov	pc, lr			@ back to caller.
121
122omap243x_sdi_cm_clksel2_pll:
123	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
124omap243x_sdi_sdrc_dlla_ctrl:
125	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
126omap243x_sdi_prcm_voltctrl:
127	.word OMAP243X_PRCM_VOLTCTRL
128prcm_mask_val:
129	.word 0xFFFF3FFC
130omap243x_sdi_timer_32ksynct_cr:
131	.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
132ENTRY(omap243x_sram_ddr_init_sz)
133	.word	. - omap243x_sram_ddr_init
134
135/*
136 * Reprograms memory timings.
137 * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
138 * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
139 */
140ENTRY(omap243x_sram_reprogram_sdrc)
141	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
142	mov	r3, #0x0		@ clear for mrc call
143	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier, finish ARM SDR/DDR
144	nop
145	nop
146	ldr	r6, omap243x_srs_sdrc_rfr_ctrl	@ get addr of refresh reg
147	ldr	r5, [r6]		@ get value
148	mov	r5, r5, lsr #8		@ isolate rfr field and drop burst
149
150	cmp	r0, #0x1		@ going to half speed?
151	movne	r9, #0x0		@ if up set flag up for pre up, hi volt
152
153	blne	voltage_shift_c		@ adjust voltage
154
155	cmp	r0, #0x1		@ going to half speed (post branch link)
156	moveq	r5, r5, lsr #1		@ divide by 2 if to half
157	movne	r5, r5, lsl #1		@ mult by 2 if to full
158	mov	r5, r5, lsl #8		@ put rfr field back into place
159	add	r5, r5, #0x1		@ turn on burst of 1
160	ldr	r4, omap243x_srs_cm_clksel2_pll	@ get address of out reg
161	ldr	r3, [r4]		@ get curr value
162	orr	r3, r3, #0x3
163	bic	r3, r3, #0x3		@ clear lower bits
164	orr	r3, r3, r0		@ new state value
165	str	r3, [r4]		@ set new state (pll/x, x=1 or 2)
166	nop
167	nop
168
169	moveq	r9, #0x1		@ if speed down, post down, drop volt
170	bleq	voltage_shift_c
171
172	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier
173	str	r5, [r6]		@ set new RFR_1 value
174	add	r6, r6, #0x30		@ get RFR_2 addr
175	str	r5, [r6]		@ set RFR_2
176	nop
177	cmp	r2, #0x1		@ (SDR or DDR) do we need to adjust DLL
178	bne	freq_out		@ leave if SDR, no DLL function
179
180	/* With DDR, we need to take care of the DLL for the frequency change */
181	ldr	r2, omap243x_srs_sdrc_dlla_ctrl	@ addr of dlla ctrl
182	str	r1, [r2]		@ write out new SDRC_DLLA_CTRL
183	add	r2, r2, #0x8		@ addr to SDRC_DLLB_CTRL
184	str	r1, [r2]		@ commit to SDRC_DLLB_CTRL
185	mov	r1, #0x2000		@ wait DLL relock, min 0x400 L3 clocks
186dll_wait:
187	subs	r1, r1, #0x1
188	bne	dll_wait
189freq_out:
190	ldmfd	sp!, {r0 - r10, pc}	@ restore regs and return
191
192    /*
193     * shift up or down voltage, use R9 as input to tell level.
194     *	wait for it to finish, use 32k sync counter, 1tick=31uS.
195     */
196voltage_shift_c:
197	ldr	r10, omap243x_srs_prcm_voltctrl	@ get addr of volt ctrl
198	ldr	r8, [r10]		@ get value
199	ldr	r7, ddr_prcm_mask_val	@ get value of mask
200	and	r8, r8, r7		@ apply mask to clear bits
201	orr	r8, r8, r9		@ bulld value for L0/L1-volt operation.
202	str	r8, [r10]		@ set up for change.
203	mov	r7, #0x4000		@ get val for force
204	orr	r8, r8, r7		@ build value for force
205	str	r8, [r10]		@ Force transition to L1
206
207	ldr	r10, omap243x_srs_timer_32ksynct	@ get addr of counter
208	ldr	r8, [r10]		@ get value
209	add	r8, r8, #0x2		@ give it at most 62uS (min 31+)
210volt_delay_c:
211	ldr	r7, [r10]		@ get timer value
212	cmp	r8, r7			@ time up?
213	bhi	volt_delay_c		@ not yet->branch
214	mov	pc, lr			@ back to caller
215
216omap243x_srs_cm_clksel2_pll:
217	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
218omap243x_srs_sdrc_dlla_ctrl:
219	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
220omap243x_srs_sdrc_rfr_ctrl:
221	.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
222omap243x_srs_prcm_voltctrl:
223	.word OMAP243X_PRCM_VOLTCTRL
224ddr_prcm_mask_val:
225	.word 0xFFFF3FFC
226omap243x_srs_timer_32ksynct:
227	.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
228
229ENTRY(omap243x_sram_reprogram_sdrc_sz)
230	.word	. - omap243x_sram_reprogram_sdrc
231
232/*
233 * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
234 */
235ENTRY(omap243x_sram_set_prcm)
236	stmfd	sp!, {r0-r12, lr}	@ regs to stack
237	adr	r4, pbegin		@ addr of preload start
238	adr	r8, pend		@ addr of preload end
239	mcrr	p15, 1, r8, r4, c12	@ preload into icache
240pbegin:
241	/* move into fast relock bypass */
242	ldr	r8, omap243x_ssp_pll_ctl	@ get addr
243	ldr	r5, [r8]		@ get val
244	mvn	r6, #0x3		@ clear mask
245	and	r5, r5, r6		@ clear field
246	orr	r7, r5, #0x2		@ fast relock val
247	str	r7, [r8]		@ go to fast relock
248	ldr	r4, omap243x_ssp_pll_stat	@ addr of stat
249block:
250	/* wait for bypass */
251	ldr	r8, [r4]		@ stat value
252	and	r8, r8, #0x3		@ mask for stat
253	cmp	r8, #0x1		@ there yet
254	bne	block			@ loop if not
255
256	/* set new dpll dividers _after_ in bypass */
257	ldr	r4, omap243x_ssp_pll_div	@ get addr
258	str	r0, [r4]		@ set dpll ctrl val
259
260	ldr	r4, omap243x_ssp_set_config	@ get addr
261	mov	r8, #1			@ valid cfg msk
262	str	r8, [r4]		@ make dividers take
263
264	mov	r4, #100		@ dead spin a bit
265wait_a_bit:
266	subs	r4, r4, #1		@ dec loop
267	bne	wait_a_bit		@ delay done?
268
269	/* check if staying in bypass */
270	cmp	r2, #0x1		@ stay in bypass?
271	beq	pend			@ jump over dpll relock
272
273	/* relock DPLL with new vals */
274	ldr	r5, omap243x_ssp_pll_stat	@ get addr
275	ldr	r4, omap243x_ssp_pll_ctl	@ get addr
276	orr	r8, r7, #0x3		@ val for lock dpll
277	str	r8, [r4]		@ set val
278	mov	r0, #1000		@ dead spin a bit
279wait_more:
280	subs	r0, r0, #1		@ dec loop
281	bne	wait_more		@ delay done?
282wait_lock:
283	ldr	r8, [r5]		@ get lock val
284	and	r8, r8, #3		@ isolate field
285	cmp	r8, #2			@ locked?
286	bne	wait_lock		@ wait if not
287pend:
288	/* update memory timings & briefly lock dll */
289	ldr	r4, omap243x_ssp_sdrc_rfr	@ get addr
290	str	r1, [r4]		@ update refresh timing
291	ldr	r11, omap243x_ssp_dlla_ctrl	@ get addr of DLLA ctrl
292	ldr	r10, [r11]		@ get current val
293	mvn	r9, #0x4		@ mask to get clear bit2
294	and	r10, r10, r9		@ clear bit2 for lock mode
295	orr	r10, r10, #0x8		@ make sure DLL on (es2 bit pos)
296	str	r10, [r11]		@ commit to DLLA_CTRL
297	add	r11, r11, #0x8		@ move to dllb
298	str	r10, [r11]		@ hit DLLB also
299
300	mov	r4, #0x800		@ relock time (min 0x400 L3 clocks)
301wait_dll_lock:
302	subs	r4, r4, #0x1
303	bne	wait_dll_lock
304	nop
305	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
306
307omap243x_ssp_set_config:
308	.word OMAP243X_PRCM_CLKCFG_CTRL
309omap243x_ssp_pll_ctl:
310	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN)
311omap243x_ssp_pll_stat:
312	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_IDLEST)
313omap243x_ssp_pll_div:
314	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
315omap243x_ssp_sdrc_rfr:
316	.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
317omap243x_ssp_dlla_ctrl:
318	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
319
320ENTRY(omap243x_sram_set_prcm_sz)
321	.word	. - omap243x_sram_set_prcm
322