summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx6/mx6_wfi.S
blob: a616dabc4a80e7e9f8fe982b5586a0661e7b2851 (plain)
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
/*
 * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <linux/linkage.h>
#include <mach/hardware.h>

/*
 *  mx6_wait
 *
 *  Idle the processor (eg, wait for interrupt).
 *  Make sure DDR is in self-refresh.
 *  IRQs are already disabled.
 */
ENTRY(mx6_wait)

    push {r4, r5, r6, r7, r8}

    mov    r7, r2       /* Store the arm_podf to be used. */
    mov   r6, r3

    ldr     r2, =ANATOP_BASE_ADDR
    add   r2, r2, #PERIPBASE_VIRT

    ldr     r8, =CCM_BASE_ADDR
    add   r8, r8, #PERIPBASE_VIRT


    /* get the flags variables into the cache */
    ldr     r3, [r0]

    /* get CPU ID */
    mrc     p15,0,r5,c0,c0,5
    and     r5, r5, #0x3

    mov r4,#0xff
    strb r4,[r0,r5]

    dsb

    mvn r4, #0x0
    ldr r3, [r0]
    cmp r3, r4
    bne DO_WFI

    mov r4, #0x1
    ldrex r3, [r1]
    cmp r3, #0x0
    strexeq r3, r4, [r1]
    cmpeq r3, #0x0
    bne DO_WFI

    mov r3, #0xff

    /* Check to see if we need to switch to 24MHz */
    cmp    r7, #0
    bne    use_podf
    ldr     r6, =(1 << 16)
    str     r6, [r2, #0x04]
    b      cont

use_podf:
    /* Change ARM_PODF to the max possible podf
     * so that ARM_CLK to IPG_CLK is in 12:5 ratio.
     */
    str    r7, [r8, #0x10]
    /* Loop till podf is accepted. */
podf_loop:
     ldr     r4, [r8, #0x48]
     cmp   r4, #0x0
     bne   podf_loop

    /* dmb */

cont:
    str r3, [r1]

    dsb

    mvn r4, #0x0
    ldr r3, [r0]
    cmp r3, r4
    beq   DO_WFI

    mov   r3, #0x0
    /* Switch to 24MHz or use ARM_PODF. */
    cmp   r7, #0x0
    bne    use_podf1
    str     r6, [r2, #0x08]
    b       DO_WFI
use_podf1:
    str     r6, [r8, #0x10]

    str r3, [r1]

DO_WFI:
	dsb

	wfi

    mov r4, #0x0
    strb r4, [r0, r5]

    dsb

    ldr r3, [r1]
    cmp r3, #0xff
    bne DONE

    mov r4, #0x0
    cmp   r7, #0x0
    bne    use_podf2
    ldr     r6, =(1 << 16)
    str     r6, [r2, #0x08]
    b       cont1

use_podf2:
    str     r6, [r8, #0x10]

cont1:
    mov r3, #0x0
    str r3, [r1]

DONE:

    pop {r4,r5, r6, r7, r8}

    /* Restore registers */
    mov     pc, lr

    .type   mx6_do_wait, #object
ENTRY(mx6_do_wait)
    .word   mx6_wait
    .size    mx6_wait, . - mx6_wait