Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/kernel/idle_6xx.S
10817 views
1
/*
2
* This file contains the power_save function for 6xx & 7xxx CPUs
3
* rewritten in assembler
4
*
5
* Warning ! This code assumes that if your machine has a 750fx
6
* it will have PLL 1 set to low speed mode (used during NAP/DOZE).
7
* if this is not the case some additional changes will have to
8
* be done to check a runtime var (a bit like powersave-nap)
9
*
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License
12
* as published by the Free Software Foundation; either version
13
* 2 of the License, or (at your option) any later version.
14
*/
15
16
#include <linux/threads.h>
17
#include <asm/reg.h>
18
#include <asm/page.h>
19
#include <asm/cputable.h>
20
#include <asm/thread_info.h>
21
#include <asm/ppc_asm.h>
22
#include <asm/asm-offsets.h>
23
24
.text
25
26
/*
27
* Init idle, called at early CPU setup time from head.S for each CPU
28
* Make sure no rest of NAP mode remains in HID0, save default
29
* values for some CPU specific registers. Called with r24
30
* containing CPU number and r3 reloc offset
31
*/
32
_GLOBAL(init_idle_6xx)
33
BEGIN_FTR_SECTION
34
mfspr r4,SPRN_HID0
35
rlwinm r4,r4,0,10,8 /* Clear NAP */
36
mtspr SPRN_HID0, r4
37
b 1f
38
END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
39
blr
40
1:
41
slwi r5,r24,2
42
add r5,r5,r3
43
BEGIN_FTR_SECTION
44
mfspr r4,SPRN_MSSCR0
45
addis r6,r5, nap_save_msscr0@ha
46
stw r4,nap_save_msscr0@l(r6)
47
END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
48
BEGIN_FTR_SECTION
49
mfspr r4,SPRN_HID1
50
addis r6,r5,nap_save_hid1@ha
51
stw r4,nap_save_hid1@l(r6)
52
END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
53
blr
54
55
/*
56
* Here is the power_save_6xx function. This could eventually be
57
* split into several functions & changing the function pointer
58
* depending on the various features.
59
*/
60
_GLOBAL(ppc6xx_idle)
61
/* Check if we can nap or doze, put HID0 mask in r3
62
*/
63
lis r3, 0
64
BEGIN_FTR_SECTION
65
lis r3,HID0_DOZE@h
66
END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
67
BEGIN_FTR_SECTION
68
/* We must dynamically check for the NAP feature as it
69
* can be cleared by CPU init after the fixups are done
70
*/
71
lis r4,cur_cpu_spec@ha
72
lwz r4,cur_cpu_spec@l(r4)
73
lwz r4,CPU_SPEC_FEATURES(r4)
74
andi. r0,r4,CPU_FTR_CAN_NAP
75
beq 1f
76
/* Now check if user or arch enabled NAP mode */
77
lis r4,powersave_nap@ha
78
lwz r4,powersave_nap@l(r4)
79
cmpwi 0,r4,0
80
beq 1f
81
lis r3,HID0_NAP@h
82
1:
83
END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
84
cmpwi 0,r3,0
85
beqlr
86
87
/* Some pre-nap cleanups needed on some CPUs */
88
andis. r0,r3,HID0_NAP@h
89
beq 2f
90
BEGIN_FTR_SECTION
91
/* Disable L2 prefetch on some 745x and try to ensure
92
* L2 prefetch engines are idle. As explained by errata
93
* text, we can't be sure they are, we just hope very hard
94
* that well be enough (sic !). At least I noticed Apple
95
* doesn't even bother doing the dcbf's here...
96
*/
97
mfspr r4,SPRN_MSSCR0
98
rlwinm r4,r4,0,0,29
99
sync
100
mtspr SPRN_MSSCR0,r4
101
sync
102
isync
103
lis r4,KERNELBASE@h
104
dcbf 0,r4
105
dcbf 0,r4
106
dcbf 0,r4
107
dcbf 0,r4
108
END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
109
2:
110
BEGIN_FTR_SECTION
111
/* Go to low speed mode on some 750FX */
112
lis r4,powersave_lowspeed@ha
113
lwz r4,powersave_lowspeed@l(r4)
114
cmpwi 0,r4,0
115
beq 1f
116
mfspr r4,SPRN_HID1
117
oris r4,r4,0x0001
118
mtspr SPRN_HID1,r4
119
1:
120
END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
121
122
/* Go to NAP or DOZE now */
123
mfspr r4,SPRN_HID0
124
lis r5,(HID0_NAP|HID0_SLEEP)@h
125
BEGIN_FTR_SECTION
126
oris r5,r5,HID0_DOZE@h
127
END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
128
andc r4,r4,r5
129
or r4,r4,r3
130
BEGIN_FTR_SECTION
131
oris r4,r4,HID0_DPM@h /* that should be done once for all */
132
END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
133
mtspr SPRN_HID0,r4
134
BEGIN_FTR_SECTION
135
DSSALL
136
sync
137
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
138
rlwinm r9,r1,0,0,31-THREAD_SHIFT /* current thread_info */
139
lwz r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
140
ori r8,r8,_TLF_NAPPING /* so when we take an exception */
141
stw r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
142
mfmsr r7
143
ori r7,r7,MSR_EE
144
oris r7,r7,MSR_POW@h
145
1: sync
146
mtmsr r7
147
isync
148
b 1b
149
150
/*
151
* Return from NAP/DOZE mode, restore some CPU specific registers,
152
* we are called with DR/IR still off and r2 containing physical
153
* address of current. R11 points to the exception frame (physical
154
* address). We have to preserve r10.
155
*/
156
_GLOBAL(power_save_ppc32_restore)
157
lwz r9,_LINK(r11) /* interrupted in ppc6xx_idle: */
158
stw r9,_NIP(r11) /* make it do a blr */
159
160
#ifdef CONFIG_SMP
161
rlwinm r12,r11,0,0,31-THREAD_SHIFT
162
lwz r11,TI_CPU(r12) /* get cpu number * 4 */
163
slwi r11,r11,2
164
#else
165
li r11,0
166
#endif
167
/* Todo make sure all these are in the same page
168
* and load r11 (@ha part + CPU offset) only once
169
*/
170
BEGIN_FTR_SECTION
171
mfspr r9,SPRN_HID0
172
andis. r9,r9,HID0_NAP@h
173
beq 1f
174
addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
175
lwz r9,nap_save_msscr0@l(r9)
176
mtspr SPRN_MSSCR0, r9
177
sync
178
isync
179
1:
180
END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
181
BEGIN_FTR_SECTION
182
addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
183
lwz r9,nap_save_hid1@l(r9)
184
mtspr SPRN_HID1, r9
185
END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
186
b transfer_to_handler_cont
187
188
.data
189
190
_GLOBAL(nap_save_msscr0)
191
.space 4*NR_CPUS
192
193
_GLOBAL(nap_save_hid1)
194
.space 4*NR_CPUS
195
196
_GLOBAL(powersave_lowspeed)
197
.long 0
198
199