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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.