hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * (C) Copyright 2007
 * Texas Instruments
 * Karthik Dasu <karthik-dp@ti.com>
 *
 * (C) Copyright 2004
 * Texas Instruments, <www.ti.com>
 * Richard Woodruff <r-woodruff2@ti.com>
 */
#include <linux/linkage.h>
 
#include <asm/assembler.h>
 
#include "omap34xx.h"
#include "iomap.h"
#include "cm3xxx.h"
#include "prm3xxx.h"
#include "sdrc.h"
#include "sram.h"
#include "control.h"
 
/*
 * Registers access definitions
 */
#define SDRC_SCRATCHPAD_SEM_OFFS    0xc
#define SDRC_SCRATCHPAD_SEM_V    OMAP343X_SCRATCHPAD_REGADDR\
                   (SDRC_SCRATCHPAD_SEM_OFFS)
#define PM_PREPWSTST_CORE_P    OMAP3430_PRM_BASE + CORE_MOD +\
                   OMAP3430_PM_PREPWSTST
#define PM_PWSTCTRL_MPU_P    OMAP3430_PRM_BASE + MPU_MOD + OMAP2_PM_PWSTCTRL
#define CM_IDLEST1_CORE_V    OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
#define CM_IDLEST_CKGEN_V    OMAP34XX_CM_REGADDR(PLL_MOD, CM_IDLEST)
#define SRAM_BASE_P        OMAP3_SRAM_PA
#define CONTROL_STAT        OMAP343X_CTRL_BASE + OMAP343X_CONTROL_STATUS
#define CONTROL_MEM_RTA_CTRL    (OMAP343X_CTRL_BASE +\
                   OMAP36XX_CONTROL_MEM_RTA_CTRL)
 
/* Move this as correct place is available */
#define SCRATCHPAD_MEM_OFFS    0x310
#define SCRATCHPAD_BASE_P    (OMAP343X_CTRL_BASE +\
                   OMAP343X_CONTROL_MEM_WKUP +\
                   SCRATCHPAD_MEM_OFFS)
#define SDRC_POWER_V        OMAP34XX_SDRC_REGADDR(SDRC_POWER)
#define SDRC_SYSCONFIG_P    (OMAP343X_SDRC_BASE + SDRC_SYSCONFIG)
#define SDRC_MR_0_P        (OMAP343X_SDRC_BASE + SDRC_MR_0)
#define SDRC_EMR2_0_P        (OMAP343X_SDRC_BASE + SDRC_EMR2_0)
#define SDRC_MANUAL_0_P        (OMAP343X_SDRC_BASE + SDRC_MANUAL_0)
#define SDRC_MR_1_P        (OMAP343X_SDRC_BASE + SDRC_MR_1)
#define SDRC_EMR2_1_P        (OMAP343X_SDRC_BASE + SDRC_EMR2_1)
#define SDRC_MANUAL_1_P        (OMAP343X_SDRC_BASE + SDRC_MANUAL_1)
#define SDRC_DLLA_STATUS_V    OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
#define SDRC_DLLA_CTRL_V    OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 
/*
 * This file needs be built unconditionally as ARM to interoperate correctly
 * with non-Thumb-2-capable firmware.
 */
   .arm
 
/*
 * API functions
 */
 
   .text
/*
 * L2 cache needs to be toggled for stable OFF mode functionality on 3630.
 * This function sets up a flag that will allow for this toggling to take
 * place on 3630. Hopefully some version in the future may not need this.
 */
ENTRY(enable_omap3630_toggle_l2_on_restore)
   stmfd    sp!, {lr}    @ save registers on stack
   /* Setup so that we will disable and enable l2 */
   mov    r1, #0x1
   adr    r3, l2dis_3630_offset
   ldr    r2, [r3]        @ value for offset
   str    r1, [r2, r3]        @ write to l2dis_3630
   ldmfd    sp!, {pc}    @ restore regs and return
ENDPROC(enable_omap3630_toggle_l2_on_restore)
 
/*
 * Function to call rom code to save secure ram context.
 *
 * r0 = physical address of the parameters
 */
   .arch armv7-a
   .arch_extension sec
ENTRY(save_secure_ram_context)
   stmfd    sp!, {r4 - r11, lr}    @ save registers on stack
   mov    r3, r0            @ physical address of parameters
   mov    r0, #25            @ set service ID for PPA
   mov    r12, r0            @ copy secure service ID in r12
   mov    r1, #0            @ set task id for ROM code in r1
   mov    r2, #4            @ set some flags in r2, r6
   mov    r6, #0xff
   dsb                @ data write barrier
   dmb                @ data memory barrier
   smc    #1            @ call SMI monitor (smi #1)
   nop
   nop
   nop
   nop
   ldmfd    sp!, {r4 - r11, pc}
ENDPROC(save_secure_ram_context)
 
/*
 * ======================
 * == Idle entry point ==
 * ======================
 */
 
/*
 * Forces OMAP into idle state
 *
 * omap34xx_cpu_suspend() - This bit of code saves the CPU context if needed
 * and executes the WFI instruction. Calling WFI effectively changes the
 * power domains states to the desired target power states.
 *
 *
 * Notes:
 * - only the minimum set of functions gets copied to internal SRAM at boot
 *   and after wake-up from OFF mode, cf. omap_push_sram_idle. The function
 *   pointers in SDRAM or SRAM are called depending on the desired low power
 *   target state.
 * - when the OMAP wakes up it continues at different execution points
 *   depending on the low power mode (non-OFF vs OFF modes),
 *   cf. 'Resume path for xxx mode' comments.
 */
   .align    3
ENTRY(omap34xx_cpu_suspend)
   stmfd    sp!, {r4 - r11, lr}    @ save registers on stack
 
   /*
    * r0 contains information about saving context:
    *   0 - No context lost
    *   1 - Only L1 and logic lost
    *   2 - Only L2 lost (Even L1 is retained we clean it along with L2)
    *   3 - Both L1 and L2 lost and logic lost
    */
 
   /*
    * For OFF mode: save context and jump to WFI in SDRAM (omap3_do_wfi)
    * For non-OFF modes: jump to the WFI code in SRAM (omap3_do_wfi_sram)
    */
   ldr    r4, omap3_do_wfi_sram_addr
   ldr    r5, [r4]
   cmp    r0, #0x0        @ If no context save required,
   bxeq    r5            @  jump to the WFI code in SRAM
 
 
   /* Otherwise fall through to the save context code */
save_context_wfi:
   /*
    * jump out to kernel flush routine
    *  - reuse that code is better
    *  - it executes in a cached space so is faster than refetch per-block
    *  - should be faster and will change with kernel
    *  - 'might' have to copy address, load and jump to it
    * Flush all data from the L1 data cache before disabling
    * SCTLR.C bit.
    */
   ldr    r1, kernel_flush
   mov    lr, pc
   bx    r1
 
   /*
    * Clear the SCTLR.C bit to prevent further data cache
    * allocation. Clearing SCTLR.C would make all the data accesses
    * strongly ordered and would not hit the cache.
    */
   mrc    p15, 0, r0, c1, c0, 0
   bic    r0, r0, #(1 << 2)    @ Disable the C bit
   mcr    p15, 0, r0, c1, c0, 0
   isb
 
   /*
    * Invalidate L1 data cache. Even though only invalidate is
    * necessary exported flush API is used here. Doing clean
    * on already clean cache would be almost NOP.
    */
   ldr    r1, kernel_flush
   blx    r1
   b    omap3_do_wfi
ENDPROC(omap34xx_cpu_suspend)
omap3_do_wfi_sram_addr:
   .word omap3_do_wfi_sram
kernel_flush:
   .word v7_flush_dcache_all
 
/* ===================================
 * == WFI instruction => Enter idle ==
 * ===================================
 */
 
/*
 * Do WFI instruction
 * Includes the resume path for non-OFF modes
 *
 * This code gets copied to internal SRAM and is accessible
 * from both SDRAM and SRAM:
 * - executed from SRAM for non-off modes (omap3_do_wfi_sram),
 * - executed from SDRAM for OFF mode (omap3_do_wfi).
 */
   .align    3
ENTRY(omap3_do_wfi)
   ldr    r4, sdrc_power        @ read the SDRC_POWER register
   ldr    r5, [r4]        @ read the contents of SDRC_POWER
   orr    r5, r5, #0x40        @ enable self refresh on idle req
   str    r5, [r4]        @ write back to SDRC_POWER register
 
   /* Data memory barrier and Data sync barrier */
   dsb
   dmb
 
/*
 * ===================================
 * == WFI instruction => Enter idle ==
 * ===================================
 */
   wfi                @ wait for interrupt
 
/*
 * ===================================
 * == Resume path for non-OFF modes ==
 * ===================================
 */
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
 
/*
 * This function implements the erratum ID i581 WA:
 *  SDRC state restore before accessing the SDRAM
 *
 * Only used at return from non-OFF mode. For OFF
 * mode the ROM code configures the SDRC and
 * the DPLL before calling the restore code directly
 * from DDR.
 */
 
/* Make sure SDRC accesses are ok */
wait_sdrc_ok:
 
/* DPLL3 must be locked before accessing the SDRC. Maybe the HW ensures this */
   ldr    r4, cm_idlest_ckgen
wait_dpll3_lock:
   ldr    r5, [r4]
   tst    r5, #1
   beq    wait_dpll3_lock
 
   ldr    r4, cm_idlest1_core
wait_sdrc_ready:
   ldr    r5, [r4]
   tst    r5, #0x2
   bne    wait_sdrc_ready
   /* allow DLL powerdown upon hw idle req */
   ldr    r4, sdrc_power
   ldr    r5, [r4]
   bic    r5, r5, #0x40
   str    r5, [r4]
 
is_dll_in_lock_mode:
   /* Is dll in lock mode? */
   ldr    r4, sdrc_dlla_ctrl
   ldr    r5, [r4]
   tst    r5, #0x4
   bne    exit_nonoff_modes    @ Return if locked
   /* wait till dll locks */
wait_dll_lock_timed:
   ldr    r4, sdrc_dlla_status
   /* Wait 20uS for lock */
   mov    r6, #8
wait_dll_lock:
   subs    r6, r6, #0x1
   beq    kick_dll
   ldr    r5, [r4]
   and    r5, r5, #0x4
   cmp    r5, #0x4
   bne    wait_dll_lock
   b    exit_nonoff_modes    @ Return when locked
 
   /* disable/reenable DLL if not locked */
kick_dll:
   ldr    r4, sdrc_dlla_ctrl
   ldr    r5, [r4]
   mov    r6, r5
   bic    r6, #(1<<3)        @ disable dll
   str    r6, [r4]
   dsb
   orr    r6, r6, #(1<<3)        @ enable dll
   str    r6, [r4]
   dsb
   b    wait_dll_lock_timed
 
exit_nonoff_modes:
   /* Re-enable C-bit if needed */
   mrc    p15, 0, r0, c1, c0, 0
   tst    r0, #(1 << 2)        @ Check C bit enabled?
   orreq    r0, r0, #(1 << 2)    @ Enable the C bit if cleared
   mcreq    p15, 0, r0, c1, c0, 0
   isb
 
/*
 * ===================================
 * == Exit point from non-OFF modes ==
 * ===================================
 */
   ldmfd    sp!, {r4 - r11, pc}    @ restore regs and return
ENDPROC(omap3_do_wfi)
sdrc_power:
   .word    SDRC_POWER_V
cm_idlest1_core:
   .word    CM_IDLEST1_CORE_V
cm_idlest_ckgen:
   .word    CM_IDLEST_CKGEN_V
sdrc_dlla_status:
   .word    SDRC_DLLA_STATUS_V
sdrc_dlla_ctrl:
   .word    SDRC_DLLA_CTRL_V
ENTRY(omap3_do_wfi_sz)
   .word    . - omap3_do_wfi
 
 
/*
 * ==============================
 * == Resume path for OFF mode ==
 * ==============================
 */
 
/*
 * The restore_* functions are called by the ROM code
 *  when back from WFI in OFF mode.
 * Cf. the get_*restore_pointer functions.
 *
 *  restore_es3: applies to 34xx >= ES3.0
 *  restore_3630: applies to 36xx
 *  restore: common code for 3xxx
 *
 * Note: when back from CORE and MPU OFF mode we are running
 *  from SDRAM, without MMU, without the caches and prediction.
 *  Also the SRAM content has been cleared.
 */
ENTRY(omap3_restore_es3)
   ldr    r5, pm_prepwstst_core_p
   ldr    r4, [r5]
   and    r4, r4, #0x3
   cmp    r4, #0x0    @ Check if previous power state of CORE is OFF
   bne    omap3_restore    @ Fall through to OMAP3 common code
   adr    r0, es3_sdrc_fix
   ldr    r1, sram_base
   ldr    r2, es3_sdrc_fix_sz
   mov    r2, r2, ror #2
copy_to_sram:
   ldmia    r0!, {r3}    @ val = *src
   stmia    r1!, {r3}    @ *dst = val
   subs    r2, r2, #0x1    @ num_words--
   bne    copy_to_sram
   ldr    r1, sram_base
   blx    r1
   b    omap3_restore    @ Fall through to OMAP3 common code
ENDPROC(omap3_restore_es3)
 
ENTRY(omap3_restore_3630)
   ldr    r1, pm_prepwstst_core_p
   ldr    r2, [r1]
   and    r2, r2, #0x3
   cmp    r2, #0x0    @ Check if previous power state of CORE is OFF
   bne    omap3_restore    @ Fall through to OMAP3 common code
   /* Disable RTA before giving control */
   ldr    r1, control_mem_rta
   mov    r2, #OMAP36XX_RTA_DISABLE
   str    r2, [r1]
ENDPROC(omap3_restore_3630)
 
   /* Fall through to common code for the remaining logic */
 
ENTRY(omap3_restore)
   /*
    * Read the pwstctrl register to check the reason for mpu reset.
    * This tells us what was lost.
    */
   ldr    r1, pm_pwstctrl_mpu
   ldr    r2, [r1]
   and    r2, r2, #0x3
   cmp    r2, #0x0    @ Check if target power state was OFF or RET
   bne    logic_l1_restore
 
   adr    r1, l2dis_3630_offset    @ address for offset
   ldr    r0, [r1]        @ value for offset
   ldr    r0, [r1, r0]        @ value at l2dis_3630
   cmp    r0, #0x1    @ should we disable L2 on 3630?
   bne    skipl2dis
   mrc    p15, 0, r0, c1, c0, 1
   bic    r0, r0, #2    @ disable L2 cache
   mcr    p15, 0, r0, c1, c0, 1
skipl2dis:
   ldr    r0, control_stat
   ldr    r1, [r0]
   and    r1, #0x700
   cmp    r1, #0x300
   beq    l2_inv_gp
   adr    r0, l2_inv_api_params_offset
   ldr    r3, [r0]
   add    r3, r3, r0        @ r3 points to dummy parameters
   mov    r0, #40            @ set service ID for PPA
   mov    r12, r0            @ copy secure Service ID in r12
   mov    r1, #0            @ set task id for ROM code in r1
   mov    r2, #4            @ set some flags in r2, r6
   mov    r6, #0xff
   dsb                @ data write barrier
   dmb                @ data memory barrier
   smc    #1            @ call SMI monitor (smi #1)
   /* Write to Aux control register to set some bits */
   mov    r0, #42            @ set service ID for PPA
   mov    r12, r0            @ copy secure Service ID in r12
   mov    r1, #0            @ set task id for ROM code in r1
   mov    r2, #4            @ set some flags in r2, r6
   mov    r6, #0xff
   ldr    r4, scratchpad_base
   ldr    r3, [r4, #0xBC]        @ r3 points to parameters
   dsb                @ data write barrier
   dmb                @ data memory barrier
   smc    #1            @ call SMI monitor (smi #1)
 
#ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
   /* Restore L2 aux control register */
                   @ set service ID for PPA
   mov    r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
   mov    r12, r0            @ copy service ID in r12
   mov    r1, #0            @ set task ID for ROM code in r1
   mov    r2, #4            @ set some flags in r2, r6
   mov    r6, #0xff
   ldr    r4, scratchpad_base
   ldr    r3, [r4, #0xBC]
   adds    r3, r3, #8        @ r3 points to parameters
   dsb                @ data write barrier
   dmb                @ data memory barrier
   smc    #1            @ call SMI monitor (smi #1)
#endif
   b    logic_l1_restore
 
   .align
l2_inv_api_params_offset:
   .long    l2_inv_api_params - .
l2_inv_gp:
   /* Execute smi to invalidate L2 cache */
   mov r12, #0x1            @ set up to invalidate L2
   smc    #0            @ Call SMI monitor (smieq)
   /* Write to Aux control register to set some bits */
   ldr    r4, scratchpad_base
   ldr    r3, [r4,#0xBC]
   ldr    r0, [r3,#4]
   mov    r12, #0x3
   smc    #0            @ Call SMI monitor (smieq)
   ldr    r4, scratchpad_base
   ldr    r3, [r4,#0xBC]
   ldr    r0, [r3,#12]
   mov    r12, #0x2
   smc    #0            @ Call SMI monitor (smieq)
logic_l1_restore:
   adr    r0, l2dis_3630_offset    @ adress for offset
   ldr    r1, [r0]        @ value for offset
   ldr    r1, [r0, r1]        @ value at l2dis_3630
   cmp    r1, #0x1        @ Test if L2 re-enable needed on 3630
   bne    skipl2reen
   mrc    p15, 0, r1, c1, c0, 1
   orr    r1, r1, #2        @ re-enable L2 cache
   mcr    p15, 0, r1, c1, c0, 1
skipl2reen:
 
   /* Now branch to the common CPU resume function */
   b    cpu_resume
ENDPROC(omap3_restore)
 
   .ltorg
 
/*
 * Local variables
 */
pm_prepwstst_core_p:
   .word    PM_PREPWSTST_CORE_P
pm_pwstctrl_mpu:
   .word    PM_PWSTCTRL_MPU_P
scratchpad_base:
   .word    SCRATCHPAD_BASE_P
sram_base:
   .word    SRAM_BASE_P + 0x8000
control_stat:
   .word    CONTROL_STAT
control_mem_rta:
   .word    CONTROL_MEM_RTA_CTRL
l2dis_3630_offset:
   .long    l2dis_3630 - .
 
   .data
   .align    2
l2dis_3630:
   .word    0
 
   .data
   .align    2
l2_inv_api_params:
   .word    0x1, 0x00
 
/*
 * Internal functions
 */
 
/*
 * This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0
 * Copied to and run from SRAM in order to reconfigure the SDRC parameters.
 */
   .text
   .align    3
ENTRY(es3_sdrc_fix)
   ldr    r4, sdrc_syscfg        @ get config addr
   ldr    r5, [r4]        @ get value
   tst    r5, #0x100        @ is part access blocked
   it    eq
   biceq    r5, r5, #0x100        @ clear bit if set
   str    r5, [r4]        @ write back change
   ldr    r4, sdrc_mr_0        @ get config addr
   ldr    r5, [r4]        @ get value
   str    r5, [r4]        @ write back change
   ldr    r4, sdrc_emr2_0        @ get config addr
   ldr    r5, [r4]        @ get value
   str    r5, [r4]        @ write back change
   ldr    r4, sdrc_manual_0    @ get config addr
   mov    r5, #0x2        @ autorefresh command
   str    r5, [r4]        @ kick off refreshes
   ldr    r4, sdrc_mr_1        @ get config addr
   ldr    r5, [r4]        @ get value
   str    r5, [r4]        @ write back change
   ldr    r4, sdrc_emr2_1        @ get config addr
   ldr    r5, [r4]        @ get value
   str    r5, [r4]        @ write back change
   ldr    r4, sdrc_manual_1    @ get config addr
   mov    r5, #0x2        @ autorefresh command
   str    r5, [r4]        @ kick off refreshes
   bx    lr
 
/*
 * Local variables
 */
   .align
sdrc_syscfg:
   .word    SDRC_SYSCONFIG_P
sdrc_mr_0:
   .word    SDRC_MR_0_P
sdrc_emr2_0:
   .word    SDRC_EMR2_0_P
sdrc_manual_0:
   .word    SDRC_MANUAL_0_P
sdrc_mr_1:
   .word    SDRC_MR_1_P
sdrc_emr2_1:
   .word    SDRC_EMR2_1_P
sdrc_manual_1:
   .word    SDRC_MANUAL_1_P
ENDPROC(es3_sdrc_fix)
ENTRY(es3_sdrc_fix_sz)
   .word    . - es3_sdrc_fix