2 * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
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.
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.
15 #include <linux/linkage.h>
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
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
51 .globl mx6sx_lpm_wfi_start
52 .globl mx6sx_lpm_wfi_end
54 .macro pll_do_wait_lock
72 ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
79 /* set perclk to 6MHz */
85 /* set mmdc to 1MHz, periph2_clk2 need to be @8MHz */
88 orr r7, r7, #(0x7 << 3)
93 ldr r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
95 /* set pll1_sw to from pll1 main */
100 /* set step from osc */
105 /* set pll1_sw to from step */
110 ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
112 /* Disable PLL1 bypass output */
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.
123 ldr r7, [r10, #0x100]
125 str r7, [r10, #0x100]
137 ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
138 ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
140 /* enable pll2 and pll2_pfd2 */
149 ldr r7, [r10, #0x100]
151 str r7, [r10, #0x100]
153 /* enable PLL1 bypass output */
159 ldreq r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
160 ldrne r10, [r0, #PM_INFO_MX6Q_CCM_P_OFFSET]
162 /* set perclk back to 24MHz */
167 /* set mmdc back to 24MHz */
170 bic r7, r7, #(0x7 << 3)
173 /* set ahb div back to 24MHz */
180 /* set pll1_sw to from pll1 main */
185 /* set step from pll2_pfd2 */
190 /* set pll1_sw to from step */
196 ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
197 ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
201 .macro anatop_enter_idle
203 ldr r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
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.
213 ands r7, r7, #(1 << 31)
218 ands r7, r7, #(1 << 31)
223 ands r7, r7, #(1 << 31)
228 ands r7, r7, #(1 << 31)
233 ands r7, r7, #(1 << 31)
238 ands r7, r7, #(1 << 31)
243 ands r7, r7, #(1 << 31)
246 /* enable weak 2P5 and turn off regular 2P5 */
247 ldr r7, [r10, #0x130]
249 str r7, [r10, #0x130]
251 str r7, [r10, #0x130]
253 /* enable weak 1p1 and turn off regular 1P1 */
254 ldr r7, [r10, #0x110]
256 str r7, [r10, #0x110]
258 str r7, [r10, #0x110]
260 /* check whether ARM LDO is bypassed */
261 ldr r7, [r10, #0x140]
266 /* low power band gap enable */
267 ldr r7, [r10, #0x270]
269 str r7, [r10, #0x270]
271 /* turn off the bias current from the regular bandgap */
272 ldr r7, [r10, #0x270]
274 str r7, [r10, #0x270]
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.
282 ldr r7, [r10, #0x150]
284 str r7, [r10, #0x150]
286 /* turn off regular bandgap */
287 ldr r7, [r10, #0x150]
289 str r7, [r10, #0x150]
291 /* only switch to RC-OSC clk after TO1.2 */
292 ldr r7, [r10, #0x260]
297 /* switch to RC-OSC */
298 ldr r7, [r10, #0x270]
300 str r7, [r10, #0x270]
302 /* turn off XTAL-OSC */
303 ldr r7, [r10, #0x150]
304 orr r7, r7, #0x40000000
305 str r7, [r10, #0x150]
307 /* lower OSC current by 37.5% */
308 ldr r7, [r10, #0x150]
310 str r7, [r10, #0x150]
314 .macro anatop_exit_idle
317 ldreq r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
318 ldrne r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
320 /* increase OSC current to normal */
321 ldr r7, [r10, #0x150]
323 str r7, [r10, #0x150]
325 /* only switch to RC-OSC after TO1.2 */
326 ldr r7, [r10, #0x260]
331 /* turn on XTAL-OSC and detector */
332 ldr r7, [r10, #0x150]
333 bic r7, r7, #0x40000000
335 str r7, [r10, #0x150]
337 /* wait for XTAL stable */
339 ldr r7, [r10, #0x150]
343 /* switch to XTAL-OSC */
344 ldr r7, [r10, #0x270]
346 str r7, [r10, #0x270]
348 /* turn off XTAL-OSC detector */
349 ldr r7, [r10, #0x150]
351 str r7, [r10, #0x150]
353 /* check whether we need to enable 2P5/1P1 */
354 ldr r7, [r10, #0x110]
355 ands r7, r7, #0x40000
358 /* check whether ARM LDO is bypassed */
359 ldr r7, [r10, #0x140]
364 /* turn on regular bandgap and wait for stable */
365 ldr r7, [r10, #0x150]
367 str r7, [r10, #0x150]
369 ldr r7, [r10, #0x150]
374 * set the REFTOP_SELFBIASOFF,
375 * self-bias circuit of the band gap.
377 ldr r7, [r10, #0x150]
379 str r7, [r10, #0x150]
381 /* turn on the bias current from the regular bandgap */
382 ldr r7, [r10, #0x270]
384 str r7, [r10, #0x270]
386 /* low power band gap disable */
387 ldr r7, [r10, #0x270]
389 str r7, [r10, #0x270]
391 /* enable regular 2P5 and turn off weak 2P5 */
392 ldr r7, [r10, #0x130]
394 str r7, [r10, #0x130]
396 /* Ensure the 2P5 is up. */
398 ldr r7, [r10, #0x130]
399 ands r7, r7, #0x20000
401 ldr r7, [r10, #0x130]
403 str r7, [r10, #0x130]
405 /* enable regular 1p1 and turn off weak 1P1 */
406 ldr r7, [r10, #0x110]
408 str r7, [r10, #0x110]
410 ldr r7, [r10, #0x110]
411 ands r7, r7, #0x20000
413 ldr r7, [r10, #0x110]
415 str r7, [r10, #0x110]
419 .macro disable_l1_dcache
422 * Flush all data from the L1 data cache before disabling
426 ldr r7, =v7_flush_dcache_all
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
439 ldr r7, =v7_flush_dcache_all
446 .macro mmdc_enter_dvfs_mode
448 /* disable automatic power savings. */
449 ldr r7, [r10, #MX6Q_MMDC_MAPSR]
451 str r7, [r10, #MX6Q_MMDC_MAPSR]
453 /* disable power down timer */
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]
463 ldr r7, [r10, #MX6Q_MMDC_MAPSR]
464 ands r7, r7, #(1 << 25)
471 /* restore MMDC IO */
473 ldreq r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
474 ldrne r10, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
476 ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
477 ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET
487 ldreq r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
488 ldrne r10, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
490 /* reset read FIFO, RST_RD_FIFO */
491 ldr r7, =MX6Q_MMDC_MPDGCTRL0
493 orr r6, r6, #(1 << 31)
497 ands r6, r6, #(1 << 31)
500 /* reset FIFO a second time */
502 orr r6, r6, #(1 << 31)
506 ands r6, r6, #(1 << 31)
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]
514 ldr r7, [r10, #MX6Q_MMDC_MAPSR]
515 ands r7, r7, #(1 << 25)
518 /* enable power down timer */
523 /* enable DDR auto power saving */
524 ldr r7, [r10, #MX6Q_MMDC_MAPSR]
526 str r7, [r10, #MX6Q_MMDC_MAPSR]
532 /* lock share memory sema4 */
534 ldreq r10, [r0, #PM_INFO_MX6Q_SEMA4_V_OFFSET]
535 ldrne r10, [r0, #PM_INFO_MX6Q_SEMA4_P_OFFSET]
547 /* unlock share memory sema4 */
549 ldreq r10, [r0, #PM_INFO_MX6Q_SEMA4_V_OFFSET]
550 ldrne r10, [r0, #PM_INFO_MX6Q_SEMA4_P_OFFSET]
556 .macro tlb_set_to_ocram
559 mrc p15, 0, r7, c2, c0, 1
560 str r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
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.
575 ldr r6, =iram_tlb_phys_addr
578 /* Flush the BTAC. */
580 mcr p15, 0, r6, c7, c1, 6
582 /* Disable Branch Prediction, Z bit in SCTLR. */
583 mrc p15, 0, r6, c1, c0, 0
585 mcr p15, 0, r6, c1, c0, 0
590 /* Store the IRAM table in TTBR1 */
591 mcr p15, 0, r7, c2, c0, 1
593 /* Read TTBCR and set PD0=1, N = 1 */
594 mrc p15, 0, r6, c2, c0, 2
596 mcr p15, 0, r6, c2, c0, 2
603 mcr p15, 0, r6, c8, c3, 0
607 .macro tlb_back_to_ddr
609 /* Restore the TTBCR */
614 /* Read TTBCR and set PD0=0, N = 0 */
615 mrc p15, 0, r6, c2, c0, 2
617 mcr p15, 0, r6, c2, c0, 2
624 mcr p15, 0, r6, c8, c3, 0
629 /* Enable Branch Prediction, Z bit in SCTLR. */
630 mrc p15, 0, r6, c1, c0, 0
632 mcr p15, 0, r6, c1, c0, 0
634 /* Flush the Branch Target Address Cache (BTAC) */
636 mcr p15, 0, r6, c7, c1, 6
639 ldr r7, [r0, #PM_INFO_PM_INFO_TTBR_OFFSET]
640 mcr p15, 0, r7, c2, c0, 1
644 .extern iram_tlb_phys_addr
646 /* imx6sx_low_power_idle */
649 ENTRY(imx6sx_low_power_idle)
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]
658 * counting the resume address in iram
659 * to set it in SRC register.
661 ldr r5, =imx6sx_low_power_idle
667 /* store physical resume addr and pm_info address. */
668 ldr r10, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
672 /* save disagnostic register */
673 mrc p15, 0, r7, c15, c0, 1
674 str r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
676 /* set ARM power to be gated */
677 ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
679 str r7, [r10, #0x2a0]
683 #ifdef CONFIG_CACHE_L2X0
685 ldr r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
687 /* Wait for background operations to complete. */
689 ldr r7, [r10, #0x730]
691 bne wait_for_l2_to_idle
694 str r7, [r10, #0x730]
696 str r7, [r10, #0x100]
704 /* make sure MMDC in self-refresh */
705 ldr r10, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
708 /* save DDR IO settings */
709 ldr r10, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
711 ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
712 ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
714 save_and_set_mmdc_io_lpm:
720 bne save_and_set_mmdc_io_lpm
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
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]
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]
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
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]
760 /* enable the counter. */
761 ldr r3, [r10, #MX6Q_CCM_CCR]
762 orr r3, r3, #(0x1 << 27)
763 str r3, [r10, #MX6Q_CCM_CCR]
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]
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.
826 /* clear ARM power gate setting */
827 ldr r10, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
829 str r7, [r10, #0x2a0]
832 mrc p15, 0, r7, c1, c0, 0
833 orr r7, r7, #(1 << 2)
834 mcr p15, 0, r7, c1, c0, 0
836 #ifdef CONFIG_CACHE_L2X0
837 ldr r10, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
840 str r7, [r10, #0x100]
845 /* Restore registers */
851 /* invalidate L1 I-cache first */
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 */
858 mcr p15, 0, r1, c1, c0, 0
860 /* restore disagnostic register */
861 ldr r7, [r0, #PM_INFO_MX6Q_SAVED_DIAGNOSTIC_OFFSET]
862 mcr p15, 0, r7, c15, c0, 1
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]
869 str r7, [r10, #MX6Q_SRC_GPR1]
870 str r7, [r10, #MX6Q_SRC_GPR2]
872 /* clear ARM power gate setting */
873 ldr r10, [r0, #PM_INFO_MX6Q_GPC_P_OFFSET]
875 str r7, [r10, #0x2a0]
884 /* Restore registers */