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
| /*
| * Copyright (C) 2016 Broadcom Corporation
| *
| * This program is free software; you can redistribute it and/or modify
| * it under the terms of the GNU General Public License version 2 as
| * published by the Free Software Foundation.
| *
| * 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.
| */
|
| #include <asm/asm.h>
| #include <asm/regdef.h>
| #include <asm/mipsregs.h>
| #include <asm/bmips.h>
|
| #include "pm.h"
|
| .text
| .set noreorder
| .align 5
| .global s3_reentry
|
| /*
| * a0: AON_CTRL base register
| * a1: D-Cache line size
| */
| LEAF(brcm_pm_do_s3)
|
| /* Get the address of s3_context */
| la t0, gp_regs
| sw ra, 0(t0)
| sw s0, 4(t0)
| sw s1, 8(t0)
| sw s2, 12(t0)
| sw s3, 16(t0)
| sw s4, 20(t0)
| sw s5, 24(t0)
| sw s6, 28(t0)
| sw s7, 32(t0)
| sw gp, 36(t0)
| sw sp, 40(t0)
| sw fp, 44(t0)
|
| /* Save CP0 Status */
| mfc0 t1, CP0_STATUS
| sw t1, 48(t0)
|
| /* Write-back gp registers - cache will be gone */
| addiu t1, a1, -1
| not t1
| and t0, t1
|
| /* Flush at least 64 bytes */
| addiu t2, t0, 64
| and t2, t1
|
| 1: cache 0x17, 0(t0)
| bne t0, t2, 1b
| addu t0, a1
|
| /* Drop to deep standby */
| li t1, PM_WARM_CONFIG
| sw zero, AON_CTRL_PM_CTRL(a0)
| lw zero, AON_CTRL_PM_CTRL(a0)
| sw t1, AON_CTRL_PM_CTRL(a0)
| lw t1, AON_CTRL_PM_CTRL(a0)
|
| li t1, (PM_WARM_CONFIG | PM_PWR_DOWN)
| sw t1, AON_CTRL_PM_CTRL(a0)
| lw t1, AON_CTRL_PM_CTRL(a0)
|
| /* Enable CP0 interrupt 2 and wait for interrupt */
| mfc0 t0, CP0_STATUS
|
| li t1, ~(ST0_IM | ST0_IE)
| and t0, t1
| ori t0, STATUSF_IP2
| mtc0 t0, CP0_STATUS
| nop
| nop
| nop
| ori t0, ST0_IE
| mtc0 t0, CP0_STATUS
|
| /* Wait for interrupt */
| wait
| nop
|
| s3_reentry:
|
| /* Clear call/return stack */
| li t0, (0x06 << 16)
| mtc0 t0, $22, 2
| ssnop
| ssnop
| ssnop
|
| /* Clear jump target buffer */
| li t0, (0x04 << 16)
| mtc0 t0, $22, 2
| ssnop
| ssnop
| ssnop
|
| sync
| nop
|
| /* Setup mmu defaults */
| mtc0 zero, CP0_WIRED
| mtc0 zero, CP0_ENTRYHI
| li k0, PM_DEFAULT_MASK
| mtc0 k0, CP0_PAGEMASK
|
| li sp, BMIPS_WARM_RESTART_VEC
| la k0, plat_wired_tlb_setup
| jalr k0
| nop
|
| /* Restore general purpose registers */
| la t0, gp_regs
| lw fp, 44(t0)
| lw sp, 40(t0)
| lw gp, 36(t0)
| lw s7, 32(t0)
| lw s6, 28(t0)
| lw s5, 24(t0)
| lw s4, 20(t0)
| lw s3, 16(t0)
| lw s2, 12(t0)
| lw s1, 8(t0)
| lw s0, 4(t0)
| lw ra, 0(t0)
|
| /* Restore CP0 status */
| lw t1, 48(t0)
| mtc0 t1, CP0_STATUS
|
| /* Return to caller */
| li v0, 0
| jr ra
| nop
|
| END(brcm_pm_do_s3)
|
|