• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/linkage.h>
3#include <asm/blackfin.h>
4#include <asm/dpmc.h>
5
6#include <asm/context.S>
7
8#define PM_STACK   (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
9
10.section .l1.text
11ENTRY(_enter_hibernate)
12	/* switch stack to L1 scratch, prepare for ddr srfr */
13	P0.H = HI(PM_STACK);
14	P0.L = LO(PM_STACK);
15	SP = P0;
16
17	call _bf609_ddr_sr;
18	call _bfin_hibernate_syscontrol;
19
20	P0.H = HI(DPM0_RESTORE4);
21	P0.L = LO(DPM0_RESTORE4);
22	P1.H = _bf609_pm_data;
23	P1.L = _bf609_pm_data;
24	[P0] = P1;
25
26	P0.H = HI(DPM0_CTL);
27	P0.L = LO(DPM0_CTL);
28	R3.H = HI(0x00000010);
29	R3.L = LO(0x00000010);
30
31	bfin_init_pm_bench_cycles;
32
33	[P0] = R3;
34
35	SSYNC;
36ENDPROC(_enter_hibernate)
37
38/* DPM wake up interrupt won't wake up core on bf60x if its core IMASK
39 * is disabled. This behavior differ from bf5xx serial processor.
40 */
41ENTRY(_dummy_deepsleep)
42	[--sp] = SYSCFG;
43	[--sp] = (R7:0,P5:0);
44	cli r0;
45
46	/* get wake up interrupt ID */
47	P0.l = LO(SEC_SCI_BASE + SEC_CSID);
48	P0.h = HI(SEC_SCI_BASE + SEC_CSID);
49	R0 = [P0];
50
51	/* ACK wake up interrupt in SEC */
52	P1.l = LO(SEC_END);
53	P1.h = HI(SEC_END);
54
55	[P1] = R0;
56	SSYNC;
57
58	/* restore EVT 11 entry */
59	p0.h = hi(EVT11);
60	p0.l = lo(EVT11);
61	p1.h = _evt_evt11;
62	p1.l = _evt_evt11;
63
64	[p0] = p1;
65	SSYNC;
66
67	(R7:0,P5:0) = [sp++];
68	SYSCFG = [sp++];
69	RTI;
70ENDPROC(_dummy_deepsleep)
71
72ENTRY(_enter_deepsleep)
73	LINK 0xC;
74	[--sp] = (R7:0,P5:0);
75
76	/* Change EVT 11 entry to dummy handler for wake up event */
77	p0.h = hi(EVT11);
78	p0.l = lo(EVT11);
79	p1.h = _dummy_deepsleep;
80	p1.l = _dummy_deepsleep;
81
82	[p0] = p1;
83
84	P0.H = HI(PM_STACK);
85	P0.L = LO(PM_STACK);
86
87	EX_SCRATCH_REG = SP;
88	SP = P0;
89
90	SSYNC;
91
92	/* should put ddr to self refresh mode before sleep */
93	call _bf609_ddr_sr;
94
95	/* Set DPM controller to deep sleep mode */
96	P0.H = HI(DPM0_CTL);
97	P0.L = LO(DPM0_CTL);
98	R3.H = HI(0x00000008);
99	R3.L = LO(0x00000008);
100	[P0] = R3;
101	CSYNC;
102
103	/* Enable evt 11 in IMASK before idle, otherwise core doesn't wake up. */
104	r0.l = 0x800;
105	r0.h = 0;
106	sti r0;
107	SSYNC;
108
109	bfin_init_pm_bench_cycles;
110
111	/* Fall into deep sleep in idle*/
112	idle;
113	SSYNC;
114
115	/* Restore PLL after wake up from deep sleep */
116	call _bf609_resume_ccbuf;
117
118	/* turn ddr out of self refresh mode */
119	call _bf609_ddr_sr_exit;
120
121	SP = EX_SCRATCH_REG;
122
123	(R7:0,P5:0) = [SP++];
124	UNLINK;
125	RTS;
126ENDPROC(_enter_deepsleep)
127
128.section .text
129ENTRY(_bf609_hibernate)
130	bfin_cpu_reg_save;
131	bfin_core_mmr_save;
132
133	P0.H = _bf609_pm_data;
134	P0.L = _bf609_pm_data;
135	R1.H = 0xDEAD;
136	R1.L = 0xBEEF;
137	R2.H = .Lpm_resume_here;
138	R2.L = .Lpm_resume_here;
139	[P0++] = R1;
140	[P0++] = R2;
141	[P0++] = SP;
142
143	P1.H = _enter_hibernate;
144	P1.L = _enter_hibernate;
145
146	call (P1);
147.Lpm_resume_here:
148
149	bfin_core_mmr_restore;
150	bfin_cpu_reg_restore;
151
152	[--sp] = RETI;  /* Clear Global Interrupt Disable */
153	SP += 4;
154
155	RTS;
156
157ENDPROC(_bf609_hibernate)
158
159