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