fix to allow usb modules to compile
[linux-2.4.21-pre4.git] / arch / ppc / kernel / idle_6xx.S
1 /*
2  * BK Id: %F% %I% %G% %U% %#%
3  */
4 /*
5  *  This file contains the power_save function for 6xx & 7xxx CPUs
6  *  rewritten in assembler
7  *
8  *  Warning ! This code assumes that if your machine has a 750fx
9  *  it will have PLL 1 set to low speed mode (used during NAP/DOZE).
10  *  if this is not the case some additional changes will have to
11  *  be done to check a runtime var (a bit like powersave-nap)
12  *
13  *  This program is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU General Public License
15  *  as published by the Free Software Foundation; either version
16  *  2 of the License, or (at your option) any later version.
17  */
18
19 #include <linux/config.h>
20 #include <linux/threads.h>
21 #include <asm/processor.h>
22 #include <asm/page.h>
23 #include <asm/cputable.h>
24 #include <asm/ppc_asm.h>
25 #include "ppc_defs.h"
26
27 #undef DEBUG
28
29         .text
30
31 /*
32  * Init idle, called at early CPU setup time from head.S for each CPU
33  * Make sure no rest of NAP mode remains in HID0, save default
34  * values for some CPU specific registers. Called with r24
35  * containing CPU number and r3 reloc offset
36  */
37         .globl  init_idle_6xx
38 init_idle_6xx:
39 BEGIN_FTR_SECTION
40         mfspr   r4,SPRN_HID0
41         rlwinm  r4,r4,0,10,8    /* Clear NAP */
42         mtspr   SPRN_HID0, r4
43         b       1f
44 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
45         blr
46 1:
47         slwi    r5,r24,2
48         add     r5,r5,r3
49 BEGIN_FTR_SECTION
50         mfspr   r4,SPRN_MSSCR0
51         addis   r6,r5, nap_save_msscr0@ha
52         stw     r4,nap_save_msscr0@l(r6)
53 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
54 BEGIN_FTR_SECTION
55         mfspr   r4,SPRN_HID1
56         addis   r6,r5,nap_save_hid1@ha
57         stw     r4,nap_save_hid1@l(r6)
58 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
59         blr
60
61 /*
62  * Here is the power_save_6xx function. This could eventually be
63  * split into several functions & changing the function pointer
64  * depending on the various features.
65  */
66         .globl  power_save_6xx
67 power_save_6xx:
68         /* Check if we can nap or doze, put HID0 mask in r3
69          */
70         lis     r3, 0
71 BEGIN_FTR_SECTION
72         lis     r3,HID0_DOZE@h
73 END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
74 BEGIN_FTR_SECTION
75         /* We must dynamically check for the NAP feature as it
76          * can be cleared by CPU init after the fixups are done
77          */
78         lis     r4,cur_cpu_spec@ha
79         lwz     r4,cur_cpu_spec@l(r4)
80         lwz     r4,CPU_SPEC_FEATURES(r4)
81         andi.   r0,r4,CPU_FTR_CAN_NAP
82         beq     1f
83         /* Now check if user or arch enabled NAP mode */
84         lis     r4,powersave_nap@ha
85         lwz     r4,powersave_nap@l(r4)
86         cmpi    0,r4,0
87         beq     1f
88         lis     r3,HID0_NAP@h
89 1:      
90 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
91         cmpi    0,r3,0
92         beqlr
93
94         /* Clear MSR:EE */
95         mfmsr   r7
96         rlwinm  r0,r7,0,17,15
97         mtmsr   r0
98
99         /* Check current->need_resched */
100         lwz     r4,NEED_RESCHED(r2)
101         cmpi    0,r4,0
102         beq+    1f
103         mtmsr   r7      /* out of line this ? */
104         blr
105 1:      
106         /* Some pre-nap cleanups needed on some CPUs */
107         andis.  r0,r3,HID0_NAP@h
108         beq     2f
109 BEGIN_FTR_SECTION
110         /* Disable L2 prefetch on some 745x and try to ensure
111          * L2 prefetch engines are idle. As explained by errata
112          * text, we can't be sure they are, we just hope very hard
113          * that well be enough (sic !). At least I noticed Apple
114          * doesn't even bother doing the dcbf's here...
115          */
116         mfspr   r4,SPRN_MSSCR0
117         rlwinm  r4,r4,0,0,29
118         sync
119         mtspr   SPRN_MSSCR0,r4
120         sync
121         isync
122         lis     r4,KERNELBASE@h
123         dcbf    0,r4
124         dcbf    0,r4
125         dcbf    0,r4
126         dcbf    0,r4
127 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
128 #ifdef DEBUG
129         lis     r6,nap_enter_count@ha
130         lwz     r4,nap_enter_count@l(r6)
131         addi    r4,r4,1
132         stw     r4,nap_enter_count@l(r6)
133 #endif  
134 2:
135 BEGIN_FTR_SECTION
136         /* Go to low speed mode on some 750FX */
137         lis     r4,powersave_lowspeed@ha
138         lwz     r4,powersave_lowspeed@l(r4)
139         cmpi    0,r4,0
140         beq     1f
141         mfspr   r4,SPRN_HID1
142         oris    r4,r4,0x0001
143         mtspr   SPRN_HID1,r4
144 1:      
145 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
146
147         /* Go to NAP or DOZE now */     
148         mfspr   r4,SPRN_HID0
149         lis     r5,(HID0_NAP|HID0_SLEEP)@h
150 BEGIN_FTR_SECTION
151         oris    r5,r5,HID0_DOZE@h
152 END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
153         andc    r4,r4,r5
154         or      r4,r4,r3
155 BEGIN_FTR_SECTION
156         oris    r4,r4,HID0_DPM@h        /* that should be done once for all  */
157 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
158         mtspr   SPRN_HID0,r4
159 BEGIN_FTR_SECTION
160         DSSALL
161         sync
162 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
163         ori     r7,r7,MSR_EE /* Could be ommited (already set) */
164         oris    r7,r7,MSR_POW@h
165         sync
166         isync
167         mtmsr   r7
168         .globl  power_save_6xx_ret
169 power_save_6xx_ret:
170         isync
171         sync
172         blr
173         
174 /*
175  * Return from NAP/DOZE mode, restore some CPU specific registers,
176  * we are called with DR/IR still off and r2 containing physical
177  * address of current.
178  */
179         .globl power_save_6xx_restore
180 power_save_6xx_restore:
181         mfspr   r22,SPRN_HID0
182         rlwinm. r22,r22,0,10,8  /* Clear NAP & copy NAP bit !state to cr1 EQ */
183         cror    4*cr1+eq,4*cr0+eq,4*cr0+eq
184 BEGIN_FTR_SECTION
185         rlwinm  r22,r22,0,9,7   /* Clear DOZE */
186 END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
187         mtspr   SPRN_HID0, r22
188
189 #ifdef DEBUG
190         beq     cr1,1f
191         lis     r22,(nap_return_count-KERNELBASE)@ha
192         lwz     r24,nap_return_count@l(r22)
193         addi    r24,r24,1
194         stw     r24,nap_return_count@l(r22)
195 1:
196 #endif
197         
198         lwz     r24,PROCESSOR(r2)
199         slwi    r24,r24,2
200         /* Todo make sure all these are in the same page
201          * and load r22 (@ha part + CPU offset) only once
202          */
203 BEGIN_FTR_SECTION
204         beq     cr1,1f
205         addis   r22,r24,(nap_save_msscr0-KERNELBASE)@ha
206         lwz     r22,nap_save_msscr0@l(r22)
207         mtspr   SPRN_MSSCR0, r22
208         sync
209         isync
210 1:
211 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
212 BEGIN_FTR_SECTION
213         addis   r22,r24,(nap_save_hid1-KERNELBASE)@ha
214         lwz     r22,nap_save_hid1@l(r22)
215         mtspr   SPRN_HID1, r22
216 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
217         b       transfer_to_handler_cont
218
219         .data
220
221         .globl nap_save_msscr0
222 nap_save_msscr0:
223         .space  4*NR_CPUS
224
225         .globl nap_save_hid1
226 nap_save_hid1:
227         .space  4*NR_CPUS
228
229 #ifdef DEBUG
230         .globl nap_enter_count
231 nap_enter_count:
232         .space  4
233         .globl nap_return_count
234 nap_return_count:
235         .space  4
236 #endif