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