]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-imx/imx6sx_low_power_idle.S
dd0a22086c5b72ce0b1658b9a0b9adbd80bb6827
[karo-tx-linux.git] / arch / arm / mach-imx / imx6sx_low_power_idle.S
1 /*
2  * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include <linux/linkage.h>
16
17 #define PM_INFO_PBASE_OFFSET                    0x0
18 #define PM_INFO_RESUME_ADDR_OFFSET              0x4
19 #define PM_INFO_PM_INFO_SIZE_OFFSET             0x8
20 #define PM_INFO_PM_INFO_TTBR_OFFSET             0xc
21 #define PM_INFO_MX6Q_MMDC_P_OFFSET              0x10
22 #define PM_INFO_MX6Q_MMDC_V_OFFSET              0x14
23 #define PM_INFO_MX6Q_IOMUXC_P_OFFSET            0x18
24 #define PM_INFO_MX6Q_IOMUXC_V_OFFSET            0x1c
25 #define PM_INFO_MX6Q_CCM_P_OFFSET               0x20
26 #define PM_INFO_MX6Q_CCM_V_OFFSET               0x24
27 #define PM_INFO_MX6Q_GPC_P_OFFSET               0x28
28 #define PM_INFO_MX6Q_GPC_V_OFFSET               0x2c
29 #define PM_INFO_MX6Q_L2_P_OFFSET                0x30
30 #define PM_INFO_MX6Q_L2_V_OFFSET                0x34
31 #define PM_INFO_MX6Q_ANATOP_P_OFFSET            0x38
32 #define PM_INFO_MX6Q_ANATOP_V_OFFSET            0x3c
33 #define PM_INFO_MX6Q_SRC_P_OFFSET               0x40
34 #define PM_INFO_MX6Q_SRC_V_OFFSET               0x44
35 #define PM_INFO_MX6Q_SEMA4_P_OFFSET             0x48
36 #define PM_INFO_MX6Q_SEMA4_V_OFFSET             0x4c
37 #define PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET    0x50
38 #define PM_INFO_MMDC_IO_NUM_OFFSET              0x54
39 #define PM_INFO_MMDC_IO_VAL_OFFSET              0x58
40
41 #define MX6Q_MMDC_MAPSR         0x404
42 #define MX6Q_MMDC_MPDGCTRL0     0x83c
43 #define MX6Q_SRC_GPR1   0x20
44 #define MX6Q_SRC_GPR2   0x24
45 #define MX6Q_GPC_IMR1   0x08
46 #define MX6Q_GPC_IMR2   0x0c
47 #define MX6Q_GPC_IMR3   0x10
48 #define MX6Q_GPC_IMR4   0x14
49 #define MX6Q_CCM_CCR    0x0
50
51 .globl mx6sx_lpm_wfi_start
52 .globl mx6sx_lpm_wfi_end
53
54         .macro  pll_do_wait_lock
55 1:
56         ldr     r7, [r10, r8]
57         ands    r7, #0x80000000
58         beq     1b
59
60         .endm
61
62         .macro  ccm_do_wait
63 2:
64         ldr     r7, [r10, #0x48]
65         cmp     r7, #0x0
66         bne     2b
67
68         .endm
69
70         .macro  ccm_enter_idle
71
72         ldr     r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
73
74         /* set ahb to 3MHz */
75         ldr     r7, [r10, #0x14]
76         orr     r7, r7, #0x1c00
77         str     r7, [r10, #0x14]
78
79         /* set perclk to 6MHz */
80         ldr     r7, [r10, #0x1c]
81         bic     r7, r7, #0x3f
82         orr     r7, r7, #0x3
83         str     r7, [r10, #0x1c]
84
85         /* set mmdc to 1MHz, periph2_clk2 need to be @8MHz */
86         ldr     r7, [r10, #0x14]
87         orr     r7, r7, #0x2
88         orr     r7, r7, #(0x7 << 3)
89         str     r7, [r10, #0x14]
90
91         ccm_do_wait
92
93         ldr     r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
94
95         /* enable PLL1 bypass output */
96         ldr     r7, [r10]
97         orr     r7, r7, #0x12000
98         str     r7, [r10]
99
100         ldr     r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
101
102         /* set pll1_sw to from pll1 main */
103         ldr     r7, [r10, #0xc]
104         bic     r7, r7, #0x4
105         str     r7, [r10, #0xc]
106
107         /* set step from osc */
108         ldr     r7, [r10, #0xc]
109         bic     r7, r7, #0x100
110         str     r7, [r10, #0xc]
111
112         /* set pll1_sw to from step */
113         ldr     r7, [r10, #0xc]
114         orr     r7, r7, #0x4
115         str     r7, [r10, #0xc]
116
117         ldr     r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
118
119         /* Disable PLL1 bypass output */
120         ldr     r7, [r10]
121         bic     r7, r7, #0x12000
122         str     r7, [r10]
123
124         /*
125          * disable pll2, suppose when system enter low
126          * power idle mode, only 396MHz pfd needs pll2,
127          * now we switch arm clock to OSC, we can disable
128          * pll2 now, gate pll2_pfd2 first.
129          */
130         ldr     r7, [r10, #0x100]
131         orr     r7, #0x800000
132         str     r7, [r10, #0x100]
133
134         ldr     r7, [r10, #0x30]
135         orr     r7, r7, #0x1000
136         bic     r7, r7, #0x2000
137         str     r7, [r10, #0x30]
138
139         .endm
140
141         .macro  ccm_exit_idle
142
143         cmp     r5, #0x0
144         ldreq   r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
145         ldrne   r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
146
147         /* enable pll2 and pll2_pfd2 */
148         ldr     r7, [r10, #0x30]
149         bic     r7, r7, #0x1000
150         orr     r7, r7, #0x2000
151         str     r7, [r10, #0x30]
152
153         ldr     r8, =0x30
154         pll_do_wait_lock
155
156         ldr     r7, [r10, #0x100]
157         bic     r7, #0x800000
158         str     r7, [r10, #0x100]
159
160         /* enable PLL1 bypass output */
161         ldr     r7, [r10]
162         orr     r7, r7, #0x12000
163         str     r7, [r10]
164
165         cmp     r5, #0x0
166         ldreq   r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
167         ldrne   r10, [r0, #PM_INFO_MX6Q_CCM_P_OFFSET]
168
169         /* set perclk back to 24MHz */
170         ldr     r7, [r10, #0x1c]
171         bic     r7, r7, #0x3f
172         str     r7, [r10, #0x1c]
173
174         /* set mmdc back to 24MHz */
175         ldr     r7, [r10, #0x14]
176         bic     r7, r7, #0x7
177         bic     r7, r7, #(0x7 << 3)
178         str     r7, [r10, #0x14]
179
180         /* set ahb div back to 24MHz */
181         ldr     r7, [r10, #0x14]
182         bic     r7, r7, #0x1c00
183         str     r7, [r10, #0x14]
184
185         ccm_do_wait
186
187         /* set pll1_sw to from pll1 main */
188         ldr     r7, [r10, #0xc]
189         bic     r7, r7, #0x4
190         str     r7, [r10, #0xc]
191
192         /* set step from pll2_pfd2 */
193         ldr     r7, [r10, #0xc]
194         orr     r7, r7, #0x100
195         str     r7, [r10, #0xc]
196
197         /* set pll1_sw to from step */
198         ldr     r7, [r10, #0xc]
199         orr     r7, r7, #0x4
200         str     r7, [r10, #0xc]
201
202         cmp     r5, #0x0
203         ldreq   r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
204         ldrne   r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
205
206         /* disable PLL1 bypass output */
207         ldr     r7, [r10]
208         bic     r7, r7, #0x12000
209         str     r7, [r10]
210
211         .endm
212
213         .macro  anatop_enter_idle
214
215         ldr     r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
216
217         /*
218          * check whether any PLL is enabled, as only when
219          * there is no PLLs enabled, 2P5 and 1P1 can be
220          * off and only enable weak ones.
221          */
222
223         /* arm pll1 */
224         ldr     r7, [r10, #0]
225         ands    r7, r7, #(1 << 31)
226         bne     10f
227
228         /* sys pll2 */
229         ldr     r7, [r10, #0x30]
230         ands    r7, r7, #(1 << 31)
231         bne     10f
232
233         /* usb pll3 */
234         ldr     r7, [r10, #0x10]
235         ands    r7, r7, #(1 << 31)
236         bne     10f
237
238         /* audio pll4 */
239         ldr     r7, [r10, #0x70]
240         ands    r7, r7, #(1 << 31)
241         bne     10f
242
243         /* vidio pll5 */
244         ldr     r7, [r10, #0xa0]
245         ands    r7, r7, #(1 << 31)
246         bne     10f
247
248         /* enet pll6 */
249         ldr     r7, [r10, #0xe0]
250         ands    r7, r7, #(1 << 31)
251         bne     10f
252
253         /* usb host pll7 */
254         ldr     r7, [r10, #0x20]
255         ands    r7, r7, #(1 << 31)
256         bne     10f
257
258         /* enable weak 2P5 and turn off regular 2P5 */
259         ldr     r7, [r10, #0x130]
260         orr     r7, r7, #0x40000
261         str     r7, [r10, #0x130]
262         bic     r7, r7, #0x1
263         str     r7, [r10, #0x130]
264
265         /* enable weak 1p1 and turn off regular 1P1 */
266         ldr     r7, [r10, #0x110]
267         orr     r7, r7, #0x40000
268         str     r7, [r10, #0x110]
269         bic     r7, r7, #0x1
270         str     r7, [r10, #0x110]
271
272         /* check whether ARM LDO is bypassed */
273         ldr     r7, [r10, #0x140]
274         and     r7, r7, #0x1f
275         cmp     r7, #0x1f
276         bne     10f
277
278         /* low power band gap enable */
279         ldr     r7, [r10, #0x270]
280         orr     r7, r7, #0x20
281         str     r7, [r10, #0x270]
282
283         /* turn off the bias current from the regular bandgap */
284         ldr     r7, [r10, #0x270]
285         orr     r7, r7, #0x80
286         str     r7, [r10, #0x270]
287
288         /*
289          * clear the REFTOP_SELFBIASOFF,
290          * self-bias circuit of the band gap.
291          * Per RM, should be cleared when
292          * band gap is powered down.
293          */
294         ldr     r7, [r10, #0x150]
295         bic     r7, r7, #0x8
296         str     r7, [r10, #0x150]
297
298         /* turn off regular bandgap */
299         ldr     r7, [r10, #0x150]
300         orr     r7, r7, #0x1
301         str     r7, [r10, #0x150]
302
303         /* only switch to RC-OSC clk after TO1.2 */
304         ldr     r7, [r10, #0x260]
305         and     r7, r7, #0x3
306         cmp     r7, #0x2
307         blt     10f
308
309         /* switch to RC-OSC */
310         ldr     r7, [r10, #0x270]
311         orr     r7, r7, #0x10
312         str     r7, [r10, #0x270]
313
314         /* turn off XTAL-OSC */
315         ldr     r7, [r10, #0x150]
316         orr     r7, r7, #0x40000000
317         str     r7, [r10, #0x150]
318 10:
319         /* lower OSC current by 37.5% */
320         ldr     r7, [r10, #0x150]
321         orr     r7, r7, #0x6000
322         str     r7, [r10, #0x150]
323
324         .endm
325
326         .macro anatop_exit_idle
327
328         cmp     r5, #0x0
329         ldreq   r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
330         ldrne   r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
331
332         /* increase OSC current to normal */
333         ldr     r7, [r10, #0x150]
334         bic     r7, r7, #0x6000
335         str     r7, [r10, #0x150]
336
337         /* only switch to RC-OSC after TO1.2 */
338         ldr     r7, [r10, #0x260]
339         and     r7, r7, #0x3
340         cmp     r7, #0x2
341         blt     15f
342
343         /* turn on XTAL-OSC and detector */
344         ldr     r7, [r10, #0x150]
345         bic     r7, r7, #0x40000000
346         orr     r7, r7, #0x10000
347         str     r7, [r10, #0x150]
348
349         /* wait for XTAL stable */
350 14:
351         ldr     r7, [r10, #0x150]
352         ands    r7, r7, #0x8000
353         beq     14b
354
355         /* switch to XTAL-OSC */
356         ldr     r7, [r10, #0x270]
357         bic     r7, r7, #0x10
358         str     r7, [r10, #0x270]
359
360         /* turn off XTAL-OSC detector */
361         ldr     r7, [r10, #0x150]
362         bic     r7, r7, #0x10000
363         str     r7, [r10, #0x150]
364 15:
365         /* check whether we need to enable 2P5/1P1 */
366         ldr     r7, [r10, #0x110]
367         ands    r7, r7, #0x40000
368         beq     11f
369
370         /* check whether ARM LDO is bypassed */
371         ldr     r7, [r10, #0x140]
372         and     r7, r7, #0x1f
373         cmp     r7, #0x1f
374         bne     12f
375
376         /* turn on regular bandgap and wait for stable */
377         ldr     r7, [r10, #0x150]
378         bic     r7, r7, #0x1
379         str     r7, [r10, #0x150]
380 13:
381         ldr     r7, [r10, #0x150]
382         ands    r7, #0x80
383         beq     13b
384
385         /*
386          * set the REFTOP_SELFBIASOFF,
387          * self-bias circuit of the band gap.
388          */
389         ldr     r7, [r10, #0x150]
390         orr     r7, r7, #0x8
391         str     r7, [r10, #0x150]
392
393         /* turn on the bias current from the regular bandgap */
394         ldr     r7, [r10, #0x270]
395         bic     r7, r7, #0x80
396         str     r7, [r10, #0x270]
397
398         /* low power band gap disable */
399         ldr     r7, [r10, #0x270]
400         bic     r7, r7, #0x20
401         str     r7, [r10, #0x270]
402 12:
403         /* enable regular 2P5 and turn off weak 2P5 */
404         ldr     r7, [r10, #0x130]
405         orr     r7, r7, #0x1
406         str     r7, [r10, #0x130]
407
408         /* Ensure the 2P5 is up. */
409 3:
410         ldr     r7, [r10, #0x130]
411         ands    r7, r7, #0x20000
412         beq     3b
413         ldr     r7, [r10, #0x130]
414         bic     r7, r7, #0x40000
415         str     r7, [r10, #0x130]
416
417         /* enable regular 1p1 and turn off weak 1P1 */
418         ldr     r7, [r10, #0x110]
419         orr     r7, r7, #0x1
420         str     r7, [r10, #0x110]
421 4:
422         ldr     r7, [r10, #0x110]
423         ands    r7, r7, #0x20000
424         beq     4b
425         ldr     r7, [r10, #0x110]
426         bic     r7, r7, #0x40000
427         str     r7, [r10, #0x110]
428 11:
429         .endm
430
431         .macro  disable_l1_dcache
432
433         /*
434          * Flush all data from the L1 data cache before disabling
435          * SCTLR.C bit.
436          */
437         push    {r0 - r10, lr}
438         ldr     r7, =v7_flush_dcache_all
439         mov     lr, pc
440         mov     pc, r7
441         pop     {r0 - r10, lr}
442
443         /* disable d-cache */
444         mrc     p15, 0, r7, c1, c0, 0
445         bic     r7, r7, #(1 << 2)
446         mcr     p15, 0, r7, c1, c0, 0
447         dsb
448         isb
449
450         push    {r0 - r10, lr}
451         ldr     r7, =v7_flush_dcache_all
452         mov     lr, pc
453         mov     pc, r7
454         pop     {r0 - r10, lr}
455
456         .endm
457
458         .macro mmdc_enter_dvfs_mode
459
460         /* disable automatic power savings. */
461         ldr     r7, [r10, #MX6Q_MMDC_MAPSR]
462         orr     r7, r7, #0x1
463         str     r7, [r10, #MX6Q_MMDC_MAPSR]
464
465         /* disable power down timer */
466         ldr     r7, [r10, #0x4]
467         bic     r7, r7, #0xff00
468         str     r7, [r10, #0x4]
469
470         /* make the DDR explicitly enter self-refresh. */
471         ldr     r7, [r10, #MX6Q_MMDC_MAPSR]
472         orr     r7, r7, #(1 << 21)
473         str     r7, [r10, #MX6Q_MMDC_MAPSR]
474 5:
475         ldr     r7, [r10, #MX6Q_MMDC_MAPSR]
476         ands    r7, r7, #(1 << 25)
477         beq     5b
478
479         .endm
480
481         .macro  resume_mmdc
482
483         /* restore MMDC IO */
484         cmp     r5, #0x0
485         ldreq   r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
486         ldrne   r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
487
488         ldr     r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
489         ldr     r7, =PM_INFO_MMDC_IO_VAL_OFFSET
490         add     r7, r7, r0
491 6:
492         ldr     r8, [r7], #0x4
493         ldr     r9, [r7], #0x4
494         str     r9, [r10, r8]
495         subs    r6, r6, #0x1
496         bne     6b
497
498         cmp     r5, #0x0
499         ldreq   r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
500         ldrne   r10, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
501
502         /* reset read FIFO, RST_RD_FIFO */
503         ldr     r7, =MX6Q_MMDC_MPDGCTRL0
504         ldr     r6, [r10, r7]
505         orr     r6, r6, #(1 << 31)
506         str     r6, [r10, r7]
507 7:
508         ldr     r6, [r10, r7]
509         ands    r6, r6, #(1 << 31)
510         bne     7b
511
512         /* reset FIFO a second time */
513         ldr     r6, [r10, r7]
514         orr     r6, r6, #(1 << 31)
515         str     r6, [r10, r7]
516 8:
517         ldr     r6, [r10, r7]
518         ands    r6, r6, #(1 << 31)
519         bne     8b
520
521         /* let DDR out of self-refresh */
522         ldr     r7, [r10, #MX6Q_MMDC_MAPSR]
523         bic     r7, r7, #(1 << 21)
524         str     r7, [r10, #MX6Q_MMDC_MAPSR]
525 9:
526         ldr     r7, [r10, #MX6Q_MMDC_MAPSR]
527         ands    r7, r7, #(1 << 25)
528         bne     9b
529
530         /* enable power down timer */
531         ldr     r7, [r10, #0x4]
532         orr     r7, r7, #0x5500
533         str     r7, [r10, #0x4]
534
535         /* enable DDR auto power saving */
536         ldr     r7, [r10, #MX6Q_MMDC_MAPSR]
537         bic     r7, r7, #0x1
538         str     r7, [r10, #MX6Q_MMDC_MAPSR]
539
540         .endm
541
542         .macro  sema4_lock
543
544         /* lock share memory sema4 */
545         cmp     r5, #0x0
546         ldreq   r10, [r0, #PM_INFO_MX6Q_SEMA4_V_OFFSET]
547         ldrne   r10, [r0, #PM_INFO_MX6Q_SEMA4_P_OFFSET]
548         ldrb    r6, =0x1
549 16:
550         ldrb    r7, [r10, #0x6]
551         cmp     r7, #0x0
552         bne     16b
553         strb    r6, [r10, #0x6]
554
555         .endm
556
557         .macro  sema4_unlock
558
559         /* unlock share memory sema4 */
560         cmp     r5, #0x0
561         ldreq   r10, [r0, #PM_INFO_MX6Q_SEMA4_V_OFFSET]
562         ldrne   r10, [r0, #PM_INFO_MX6Q_SEMA4_P_OFFSET]
563         ldrb    r6, =0x0
564         strb    r6, [r10, #0x6]
565
566         .endm
567
568         .macro  tlb_set_to_ocram
569
570         /* save ttbr */
571         mrc     p15, 0, r7, c2, c0, 1
572         str     r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
573
574         /*
575          * To ensure no page table walks occur in DDR, we
576          * have a another page table stored in IRAM that only
577          * contains entries pointing to IRAM, AIPS1 and AIPS2.
578          * We need to set the TTBR1 to the new IRAM TLB.
579          * Do the following steps:
580          * 1. Flush the Branch Target Address Cache (BTAC)
581          * 2. Set TTBR1 to point to IRAM page table.
582          * 3. Disable page table walks in TTBR0 (PD0 = 1)
583          * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
584          *     and 2-4G is translated by TTBR1.
585          */
586
587         ldr     r6, =iram_tlb_phys_addr
588         ldr     r7, [r6]
589
590         /* Flush the BTAC. */
591         ldr     r6, =0x0
592         mcr     p15, 0, r6, c7, c1, 6
593
594         /* Disable Branch Prediction, Z bit in SCTLR. */
595         mrc     p15, 0, r6, c1, c0, 0
596         bic     r6, r6, #0x800
597         mcr     p15, 0, r6, c1, c0, 0
598
599         dsb
600         isb
601
602         /* Store the IRAM table in TTBR1 */
603         mcr     p15, 0, r7, c2, c0, 1
604
605         /* Read TTBCR and set PD0=1, N = 1 */
606         mrc     p15, 0, r6, c2, c0, 2
607         orr     r6, r6, #0x11
608         mcr     p15, 0, r6, c2, c0, 2
609
610         dsb
611         isb
612
613         /* flush the TLB */
614         ldr     r6, =0x0
615         mcr     p15, 0, r6, c8, c3, 0
616
617         .endm
618
619         .macro  tlb_back_to_ddr
620
621         /* Restore the TTBCR */
622
623         dsb
624         isb
625
626         /* Read TTBCR and set PD0=0, N = 0 */
627         mrc     p15, 0, r6, c2, c0, 2
628         bic     r6, r6, #0x11
629         mcr     p15, 0, r6, c2, c0, 2
630
631         dsb
632         isb
633
634         /* flush the TLB */
635         ldr     r6, =0x0
636         mcr     p15, 0, r6, c8, c3, 0
637
638         dsb
639         isb
640
641         /* Enable Branch Prediction, Z bit in SCTLR. */
642         mrc     p15, 0, r6, c1, c0, 0
643         orr     r6, r6, #0x800
644         mcr     p15, 0, r6, c1, c0, 0
645
646         /* Flush the Branch Target Address Cache (BTAC) */
647         ldr     r6, =0x0
648         mcr     p15, 0, r6, c7, c1, 6
649
650         /* restore ttbr */
651         ldr     r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
652         mcr     p15, 0, r7, c2, c0, 1
653
654         .endm
655
656 .extern iram_tlb_phys_addr
657
658 /* imx6sx_low_power_idle */
659
660         .align 3
661 ENTRY(imx6sx_low_power_idle)
662 mx6sx_lpm_wfi_start:
663         push    {r4 - r10}
664
665         /* get necessary info from pm_info */
666         ldr     r1, [r0, #PM_INFO_PBASE_OFFSET]
667         ldr     r2, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
668
669         /*
670          * counting the resume address in iram
671          * to set it in SRC register.
672          */
673         ldr     r5, =imx6sx_low_power_idle
674         ldr     r6, =wakeup
675         sub     r6, r6, r5
676         add     r8, r1, r2
677         add     r3, r8, r6
678
679         /* store physical resume addr and pm_info address. */
680         ldr     r10, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
681         str     r3, [r10, #0x20]
682         str     r1, [r10, #0x24]
683
684         /* save disagnostic register */
685         mrc     p15, 0, r7, c15, c0, 1
686         str     r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
687
688         /* set ARM power to be gated */
689         ldr     r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
690         ldr     r7, =0x1
691         str     r7, [r10, #0x2a0]
692
693         disable_l1_dcache
694
695 #ifdef CONFIG_CACHE_L2X0
696         /* sync L2 */
697         ldr     r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
698
699         /* Wait for background operations to complete. */
700 wait_for_l2_to_idle:
701         ldr     r7, [r10, #0x730]
702         cmp     r7, #0x0
703         bne     wait_for_l2_to_idle
704
705         mov     r7, #0x0
706         str     r7, [r10, #0x730]
707         /* disable L2 */
708         str     r7, [r10, #0x100]
709
710         dsb
711         isb
712 #endif
713
714         tlb_set_to_ocram
715
716         /* make sure MMDC in self-refresh */
717         ldr     r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
718         mmdc_enter_dvfs_mode
719
720         /* save DDR IO settings */
721         ldr     r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
722         ldr     r6, =0x0
723         ldr     r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
724         ldr     r8, =PM_INFO_MMDC_IO_VAL_OFFSET
725         add     r8, r8, r0
726 save_and_set_mmdc_io_lpm:
727         ldr     r9, [r8], #0x4
728         ldr     r5, [r10, r9]
729         str     r6, [r10, r9]
730         str     r5, [r8], #0x4
731         subs    r7, r7, #0x1
732         bne     save_and_set_mmdc_io_lpm
733
734         mov     r5, #0x0
735         sema4_lock
736         ccm_enter_idle
737         anatop_enter_idle
738         sema4_unlock
739
740         /*
741          * mask all GPC interrupts before
742          * enabling the RBC counters to
743          * avoid the counter starting too
744          * early if an interupt is already
745          * pending.
746          */
747         ldr     r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
748         ldr     r4, [r10, #MX6Q_GPC_IMR1]
749         ldr     r5, [r10, #MX6Q_GPC_IMR2]
750         ldr     r6, [r10, #MX6Q_GPC_IMR3]
751         ldr     r7, [r10, #MX6Q_GPC_IMR4]
752
753         ldr     r3, =0xffffffff
754         str     r3, [r10, #MX6Q_GPC_IMR1]
755         str     r3, [r10, #MX6Q_GPC_IMR2]
756         str     r3, [r10, #MX6Q_GPC_IMR3]
757         str     r3, [r10, #MX6Q_GPC_IMR4]
758
759         /*
760          * enable the RBC bypass counter here
761          * to hold off the interrupts. RBC counter
762          * = 1 (30us). With this setting, the latency
763          * from wakeup interrupt to ARM power up
764          * is ~40uS.
765          */
766         ldr     r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
767         ldr     r3, [r10, #MX6Q_CCM_CCR]
768         bic     r3, r3, #(0x3f << 21)
769         orr     r3, r3, #(0x1 << 21)
770         str     r3, [r10, #MX6Q_CCM_CCR]
771
772         /* enable the counter. */
773         ldr     r3, [r10, #MX6Q_CCM_CCR]
774         orr     r3, r3, #(0x1 << 27)
775         str     r3, [r10, #MX6Q_CCM_CCR]
776
777         /* unmask all the GPC interrupts. */
778         ldr     r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
779         str     r4, [r10, #MX6Q_GPC_IMR1]
780         str     r5, [r10, #MX6Q_GPC_IMR2]
781         str     r6, [r10, #MX6Q_GPC_IMR3]
782         str     r7, [r10, #MX6Q_GPC_IMR4]
783
784         /*
785          * now delay for a short while (3usec)
786          * ARM is at 1GHz at this point
787          * so a short loop should be enough.
788          * this delay is required to ensure that
789          * the RBC counter can start counting in
790          * case an interrupt is already pending
791          * or in case an interrupt arrives just
792          * as ARM is about to assert DSM_request.
793          */
794         ldr     r4, =2000
795 rbc_loop:
796         subs    r4, r4, #0x1
797         bne     rbc_loop
798
799         wfi
800
801         nop
802         nop
803         nop
804         nop
805         nop
806
807         nop
808         nop
809         nop
810         nop
811         nop
812
813         nop
814         nop
815         nop
816         nop
817         nop
818
819         nop
820         nop
821         nop
822         nop
823         nop
824
825         nop
826         nop
827         nop
828         nop
829         nop
830
831         mov     r5, #0x0
832         sema4_lock
833         anatop_exit_idle
834         ccm_exit_idle
835         sema4_unlock
836         resume_mmdc
837
838         /* clear ARM power gate setting */
839         ldr     r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
840         ldr     r7, =0x0
841         str     r7, [r10, #0x2a0]
842
843         /* enable d-cache */
844         mrc     p15, 0, r7, c1, c0, 0
845         orr     r7, r7, #(1 << 2)
846         mcr     p15, 0, r7, c1, c0, 0
847
848 #ifdef CONFIG_CACHE_L2X0
849         ldr     r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
850         mov     r7, #0x1
851         /* enable L2 */
852         str     r7, [r10, #0x100]
853 #endif
854
855         tlb_back_to_ddr
856
857         /* Restore registers */
858         pop     {r4 - r10}
859         mov     pc, lr
860
861 wakeup:
862
863         /* invalidate L1 I-cache first */
864         mov     r1, #0x0
865         mcr     p15, 0, r1, c7, c5, 0
866         mcr     p15, 0, r1, c7, c5, 0
867         mcr     p15, 0, r1, c7, c5, 6
868         /* enable the Icache and branch prediction */
869         mov     r1, #0x1800
870         mcr     p15, 0, r1, c1, c0, 0
871         isb
872         /* restore disagnostic register */
873         ldr     r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
874         mcr     p15, 0, r7, c15, c0, 1
875
876         /* get physical resume address from pm_info. */
877         ldr     lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
878         /* clear core0's entry and parameter */
879         ldr     r10, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
880         mov     r7, #0x0
881         str     r7, [r10, #MX6Q_SRC_GPR1]
882         str     r7, [r10, #MX6Q_SRC_GPR2]
883
884         /* clear ARM power gate setting */
885         ldr     r10, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
886         ldr     r7, =0x0
887         str     r7, [r10, #0x2a0]
888
889         mov     r5, #0x1
890         sema4_lock
891         anatop_exit_idle
892         ccm_exit_idle
893         sema4_unlock
894         resume_mmdc
895
896         /* Restore registers */
897         mov     pc, lr
898         .ltorg
899 mx6sx_lpm_wfi_end: