~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/acpi/cpu.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  cpu.c - Processor handling
  3  *
  4  *  Copyright (C) 2000 Andrew Henroid
  5  *
  6  *  This program is free software; you can redistribute it and/or modify
  7  *  it under the terms of the GNU General Public License as published by
  8  *  the Free Software Foundation; either version 2 of the License, or
  9  *  (at your option) any later version.
 10  *
 11  *  This program is distributed in the hope that it will be useful,
 12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  *  GNU General Public License for more details.
 15  *
 16  *  You should have received a copy of the GNU General Public License
 17  *  along with this program; if not, write to the Free Software
 18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19  */
 20 
 21 #include <linux/config.h>
 22 #include <linux/kernel.h>
 23 #include <linux/pm.h>
 24 #include <linux/acpi.h>
 25 #include "acpi.h"
 26 #include "driver.h"
 27 
 28 #define _COMPONENT      OS_DEPENDENT
 29         MODULE_NAME     ("cpu")
 30 
 31 unsigned long acpi_c2_exit_latency = ACPI_INFINITE;
 32 unsigned long acpi_c3_exit_latency = ACPI_INFINITE;
 33 unsigned long acpi_c2_enter_latency = ACPI_INFINITE;
 34 unsigned long acpi_c3_enter_latency = ACPI_INFINITE;
 35 
 36 static unsigned long acpi_pblk = ACPI_INVALID;
 37 static int acpi_c2_tested = 0;
 38 static int acpi_c3_tested = 0;
 39 static int acpi_max_c_state = 1;
 40 static int acpi_pm_tmr_len;
 41 
 42 /*
 43  * Clear busmaster activity flag
 44  */
 45 static inline void
 46 acpi_clear_bm_activity(void)
 47 {
 48         acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 0);
 49 }
 50 
 51 /*
 52  * Returns 1 if there has been busmaster activity
 53  */
 54 static inline int
 55 acpi_bm_activity(void)
 56 {
 57         return acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, BM_STS);
 58 }
 59 
 60 /*
 61  * Set system to sleep through busmaster requests
 62  */
 63 static void
 64 acpi_sleep_on_busmaster(void)
 65 {
 66         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1);
 67 }
 68 
 69 /*
 70  * Set system to wake on busmaster requests
 71  */
 72 static void
 73 acpi_wake_on_busmaster(void)
 74 {
 75         acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0);
 76 }
 77 
 78 u32
 79 acpi_read_pm_timer(void)
 80 {
 81         return acpi_hw_register_read(ACPI_MTX_LOCK, PM_TIMER);
 82 }
 83 
 84 /*
 85  * Do a compare, accounting for 24/32bit rollover
 86  */
 87 static u32
 88 acpi_compare_pm_timers(u32 first, u32 second)
 89 {
 90         if (first < second) {
 91                 return (second - first);
 92         } else {
 93                 if (acpi_pm_tmr_len == 24)
 94                         return (second + (0xFFFFFF - first));
 95                 else
 96                         return (second + (0xFFFFFFFF - first));
 97         }
 98 }
 99 
100 /*
101  * Idle loop (uniprocessor only)
102  */
103 static void
104 acpi_idle(void)
105 {
106         static int sleep_level = 1;
107         FADT_DESCRIPTOR *fadt = &acpi_fadt;
108 
109         if (!fadt
110             || (STRNCMP(fadt->header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
111             || !fadt->Xpm_tmr_blk.address
112             || !acpi_pblk)
113                 goto not_initialized;
114 
115         /*
116          * start from the previous sleep level..
117          */
118         if (sleep_level == 1
119             || acpi_max_c_state < 2)
120                 goto sleep1;
121 
122         if (sleep_level == 2
123             || acpi_max_c_state < 3)
124                 goto sleep2;
125 
126       sleep3:
127         sleep_level = 3;
128         if (!acpi_c3_tested) {
129                 DEBUG_PRINT(ACPI_INFO, ("C3 works\n"));
130                 acpi_c3_tested = 1;
131         }
132         acpi_wake_on_busmaster();
133         if (fadt->Xpm2_cnt_blk.address)
134                 goto sleep3_with_arbiter;
135 
136         for (;;) {
137                 unsigned long time;
138                 unsigned long diff;
139                 
140                 __cli();
141                 if (current->need_resched)
142                         goto out;
143                 if (acpi_bm_activity())
144                         goto sleep2;
145 
146                 time = acpi_read_pm_timer();
147                 inb(acpi_pblk + ACPI_P_LVL3);
148                 /* Dummy read, force synchronization with the PMU */
149                 acpi_read_pm_timer();
150                 diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
151 
152                 __sti();
153                 if (diff < acpi_c3_exit_latency)
154                         goto sleep2;
155         }
156 
157       sleep3_with_arbiter:
158         for (;;) {
159                 unsigned long time;
160                 unsigned long diff;
161 
162                 __cli();
163                 if (current->need_resched)
164                         goto out;
165                 if (acpi_bm_activity())
166                         goto sleep2;
167 
168                 time = acpi_read_pm_timer();
169                 
170                 /* Disable arbiter, park on CPU */
171                 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);
172                 inb(acpi_pblk + ACPI_P_LVL3);
173                 /* Dummy read, force synchronization with the PMU */
174                 acpi_read_pm_timer();
175                 diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
176                 /* Enable arbiter again.. */
177                 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0);
178 
179                 __sti();
180                 if (diff < acpi_c3_exit_latency)
181                         goto sleep2;
182         }
183 
184       sleep2:
185         sleep_level = 2;
186         if (!acpi_c2_tested) {
187                 DEBUG_PRINT(ACPI_INFO, ("C2 works\n"));
188                 acpi_c2_tested = 1;
189         }
190         acpi_wake_on_busmaster();       /* Required to track BM activity.. */
191         for (;;) {
192                 unsigned long time;
193                 unsigned long diff;
194 
195                 __cli();
196                 if (current->need_resched)
197                         goto out;
198 
199                 time = acpi_read_pm_timer();
200                 inb(acpi_pblk + ACPI_P_LVL2);
201                 /* Dummy read, force synchronization with the PMU */
202                 acpi_read_pm_timer();
203                 diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
204 
205                 __sti();
206                 if (diff < acpi_c2_exit_latency)
207                         goto sleep1;
208                 if (acpi_bm_activity()) {
209                         acpi_clear_bm_activity();
210                         continue;
211                 }
212                 if (diff > acpi_c3_enter_latency
213                     && acpi_max_c_state >= 3)
214                         goto sleep3;
215         }
216 
217       sleep1:
218         sleep_level = 1;
219         acpi_sleep_on_busmaster();
220         for (;;) {
221                 unsigned long time;
222                 unsigned long diff;
223 
224                 __cli();
225                 if (current->need_resched)
226                         goto out;
227                 time = acpi_read_pm_timer();
228                 safe_halt();
229                 diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
230                 if (diff > acpi_c2_enter_latency
231                     && acpi_max_c_state >= 2)
232                         goto sleep2;
233         }
234 
235       not_initialized:
236         for (;;) {
237                 __cli();
238                 if (current->need_resched)
239                         goto out;
240                 safe_halt();
241         }
242 
243       out:
244         __sti();
245 }
246 
247 /*
248  * Get processor information
249  */
250 static ACPI_STATUS
251 acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
252 {
253         ACPI_OBJECT obj;
254         ACPI_CX_STATE lat[4];
255         ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE];
256         ACPI_BUFFER buf;
257         int i, count;
258 
259         buf.length = sizeof(obj);
260         buf.pointer = &obj;
261         if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf)))
262                 return AE_OK;
263 
264         DEBUG_PRINT(ACPI_INFO, ("PBLK %d @ 0x%04x:%d\n",
265                         obj.processor.proc_id,
266                         obj.processor.pblk_address,
267                         obj.processor.pblk_length));
268 
269         if (acpi_pblk != ACPI_INVALID
270             || !obj.processor.pblk_address
271             || obj.processor.pblk_length != 6)
272                 return AE_OK;
273 
274         acpi_pblk = obj.processor.pblk_address;
275 
276         buf.length = sizeof(lat);
277         buf.pointer = lat;
278         if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf)))
279                 return AE_OK;
280 
281         if (lat[2].latency < MAX_CX_STATE_LATENCY) {
282                 printk(KERN_INFO "ACPI: System firmware supports: C2");
283                 acpi_c2_exit_latency = lat[2].latency;
284                 acpi_max_c_state = 2;
285         
286                 if (lat[3].latency < MAX_CX_STATE_LATENCY) {
287                         printk(" C3");
288                         acpi_c3_exit_latency = lat[3].latency;
289                         acpi_max_c_state = 3;
290                 }
291                 printk("\n");
292         }
293 
294         memset(throttle, 0, sizeof(throttle));
295         buf.length = sizeof(throttle);
296         buf.pointer = throttle;
297 
298         if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf)))
299                 return AE_OK;
300 
301         for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) {
302                 if (throttle[i].percent_of_clock)
303                         count++;
304         }
305 
306         /* 0% throttled really doesn't count */
307         count--;
308 
309         if (count > 0) {
310                 DEBUG_PRINT(ACPI_INFO, ("%d throttling states\n", count));
311         }
312 
313         return AE_OK;
314 }
315 
316 static int
317 acpi_pm_timer_init(void)
318 {
319         FADT_DESCRIPTOR *fadt = &acpi_fadt;
320 
321         if (fadt->tmr_val_ext) {
322                 acpi_pm_tmr_len = 32;
323         } else {
324                 acpi_pm_tmr_len = 24;
325         }
326 
327         DEBUG_PRINT(ACPI_INFO, ("PM Timer width: %d bits\n", acpi_pm_tmr_len));
328 
329         return AE_OK;
330 }
331 
332 int
333 acpi_cpu_init(void)
334 {
335         acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
336                             ACPI_ROOT_OBJECT,
337                             ACPI_UINT32_MAX,
338                             acpi_found_cpu,
339                             NULL,
340                             NULL);
341 
342         acpi_pm_timer_init();
343 
344 
345 #ifdef CONFIG_SMP
346         if (smp_num_cpus == 1)
347                 pm_idle = acpi_idle;
348 #else
349         pm_idle = acpi_idle;
350 #endif
351 
352         return 0;
353 }
354 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.