summaryrefslogtreecommitdiffstats
path: root/drivers/soc/bcm/brcmstb/pm/s3-mips.S
blob: 1242308a8868c6ef45734b8e70e978d8235fe666 (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
/*
 * 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)