GNU Linux-libre 4.19.295-gnu1
[releases.git] / drivers / soc / bcm / brcmstb / pm / s3-mips.S
1 /*
2  * Copyright (C) 2016 Broadcom Corporation
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 version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  */
13
14 #include <asm/asm.h>
15 #include <asm/regdef.h>
16 #include <asm/mipsregs.h>
17 #include <asm/bmips.h>
18
19 #include "pm.h"
20
21         .text
22         .set            noreorder
23         .align          5
24         .global         s3_reentry
25
26 /*
27  * a0: AON_CTRL base register
28  * a1: D-Cache line size
29  */
30 LEAF(brcm_pm_do_s3)
31
32         /* Get the address of s3_context */
33         la      t0, gp_regs
34         sw      ra, 0(t0)
35         sw      s0, 4(t0)
36         sw      s1, 8(t0)
37         sw      s2, 12(t0)
38         sw      s3, 16(t0)
39         sw      s4, 20(t0)
40         sw      s5, 24(t0)
41         sw      s6, 28(t0)
42         sw      s7, 32(t0)
43         sw      gp, 36(t0)
44         sw      sp, 40(t0)
45         sw      fp, 44(t0)
46
47         /* Save CP0 Status */
48         mfc0    t1, CP0_STATUS
49         sw      t1, 48(t0)
50
51         /* Write-back gp registers - cache will be gone */
52         addiu   t1, a1, -1
53         not     t1
54         and     t0, t1
55
56         /* Flush at least 64 bytes */
57         addiu   t2, t0, 64
58         and     t2, t1
59
60 1:      cache   0x17, 0(t0)
61         bne     t0, t2, 1b
62         addu    t0, a1
63
64         /* Drop to deep standby */
65         li      t1, PM_WARM_CONFIG
66         sw      zero, AON_CTRL_PM_CTRL(a0)
67         lw      zero, AON_CTRL_PM_CTRL(a0)
68         sw      t1, AON_CTRL_PM_CTRL(a0)
69         lw      t1, AON_CTRL_PM_CTRL(a0)
70
71         li      t1, (PM_WARM_CONFIG | PM_PWR_DOWN)
72         sw      t1, AON_CTRL_PM_CTRL(a0)
73         lw      t1, AON_CTRL_PM_CTRL(a0)
74
75         /* Enable CP0 interrupt 2 and wait for interrupt */
76         mfc0    t0, CP0_STATUS
77
78         li      t1, ~(ST0_IM | ST0_IE)
79         and     t0, t1
80         ori     t0, STATUSF_IP2
81         mtc0    t0, CP0_STATUS
82         nop
83         nop
84         nop
85         ori     t0, ST0_IE
86         mtc0    t0, CP0_STATUS
87
88         /* Wait for interrupt */
89         wait
90         nop
91
92 s3_reentry:
93
94         /* Clear call/return stack */
95         li      t0, (0x06 << 16)
96         mtc0    t0, $22, 2
97         ssnop
98         ssnop
99         ssnop
100
101         /* Clear jump target buffer */
102         li      t0, (0x04 << 16)
103         mtc0    t0, $22, 2
104         ssnop
105         ssnop
106         ssnop
107
108         sync
109         nop
110
111         /* Setup mmu defaults */
112         mtc0    zero, CP0_WIRED
113         mtc0    zero, CP0_ENTRYHI
114         li      k0, PM_DEFAULT_MASK
115         mtc0    k0, CP0_PAGEMASK
116
117         li      sp, BMIPS_WARM_RESTART_VEC
118         la      k0, plat_wired_tlb_setup
119         jalr    k0
120         nop
121
122         /* Restore general purpose registers */
123         la      t0, gp_regs
124         lw      fp, 44(t0)
125         lw      sp, 40(t0)
126         lw      gp, 36(t0)
127         lw      s7, 32(t0)
128         lw      s6, 28(t0)
129         lw      s5, 24(t0)
130         lw      s4, 20(t0)
131         lw      s3, 16(t0)
132         lw      s2, 12(t0)
133         lw      s1, 8(t0)
134         lw      s0, 4(t0)
135         lw      ra, 0(t0)
136
137         /* Restore CP0 status */
138         lw      t1, 48(t0)
139         mtc0    t1, CP0_STATUS
140
141         /* Return to caller */
142         li      v0, 0
143         jr      ra
144         nop
145
146 END(brcm_pm_do_s3)