- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / hardware / hwcpu32.c
blobfba28acc726340bb00321b8b7e26bf747c69be11
1 /******************************************************************************
3 * Name: hwcpu32.c - CPU support for IA32 (Throttling, Cx_states)
4 * $Revision: 39 $
6 *****************************************************************************/
8 /*
9 * Copyright (C) 2000 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "acpi.h"
27 #include "acnamesp.h"
28 #include "achware.h"
30 #define _COMPONENT HARDWARE
31 MODULE_NAME ("Hwcpu32")
34 #define BIT_4 0x10 /* TBD: [investigate] is this correct? */
37 /****************************************************************************
39 * FUNCTION: Acpi_hw_enter_c1
41 * PARAMETERS: Pblk_address - Address of the processor control block
42 * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep
44 * RETURN: Function status.
46 * DESCRIPTION: Set C1 state on IA32 processor (halt)
48 ****************************************************************************/
50 ACPI_STATUS
51 acpi_hw_enter_c1(
52 ACPI_IO_ADDRESS pblk_address,
53 u32 *pm_timer_ticks)
55 u32 timer = 0;
58 if (!pm_timer_ticks) {
60 * Enter C1:
61 * ---------
63 enable();
64 halt();
65 *pm_timer_ticks = ACPI_UINT32_MAX;
67 else {
68 timer = acpi_hw_pmt_ticks ();
71 * Enter C1:
72 * ---------
74 enable ();
75 halt ();
78 * Compute Time in C1:
79 * -------------------
81 timer = acpi_hw_pmt_ticks () - timer;
83 *pm_timer_ticks = timer;
86 return (AE_OK);
90 /****************************************************************************
92 * FUNCTION: Acpi_hw_enter_c2
94 * PARAMETERS: Pblk_address - Address of the processor control block
95 * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep
97 * RETURN: <none>
99 * DESCRIPTION: Set C2 state on IA32 processor
101 ****************************************************************************/
103 ACPI_STATUS
104 acpi_hw_enter_c2(
105 ACPI_IO_ADDRESS pblk_address,
106 u32 *pm_timer_ticks)
108 u32 timer = 0;
111 if (!pblk_address || !pm_timer_ticks) {
112 return (AE_BAD_PARAMETER);
116 * Disable interrupts before all C2/C3 transitions.
118 disable ();
120 timer = acpi_hw_pmt_ticks ();
123 * Enter C2:
124 * ---------
125 * Read from the P_LVL2 (P_BLK+4) register to invoke a C2 transition.
127 acpi_os_in8 ((ACPI_IO_ADDRESS) (pblk_address + 4));
130 * Perform Dummy Op:
131 * -----------------
132 * We have to do something useless after reading LVL2 because chipsets
133 * cannot guarantee that STPCLK# gets asserted in time to freeze execution.
135 acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
138 * Compute Time in C2:
139 * -------------------
141 timer = acpi_hw_pmt_ticks () - timer;
143 *pm_timer_ticks = timer;
146 * Re-enable interrupts after coming out of C2/C3.
148 enable ();
150 return (AE_OK);
154 /****************************************************************************
156 * FUNCTION: Acpi_hw_enter_c3
158 * PARAMETERS: Pblk_address - Address of the processor control block
159 * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep
161 * RETURN: Status of function
163 * DESCRIPTION: Set C3 state on IA32 processor (UP only, cache coherency via
164 * disabling bus mastering)
166 ****************************************************************************/
168 ACPI_STATUS
169 acpi_hw_enter_c3(
170 ACPI_IO_ADDRESS pblk_address,
171 u32 *pm_timer_ticks)
173 u32 timer = 0;
174 u32 bus_master_status = 0;
177 if (!pblk_address || !pm_timer_ticks) {
178 return (AE_BAD_PARAMETER);
182 * Check the BM_STS bit, if it is set, do not enter C3
183 * but clear the bit (with a write) and exit, telling
184 * the calling module that we spent zero time in C3.
185 * If bus mastering continues, this action should
186 * eventually cause a demotion to C2
188 if (1 == (bus_master_status =
189 acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, BM_STS)))
192 * Clear the BM_STS bit by setting it.
194 acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1);
195 *pm_timer_ticks = 0;
196 return (AE_OK);
200 * Disable interrupts before all C2/C3 transitions.
202 disable();
205 * Disable Bus Mastering:
206 * ----------------------
207 * Set the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits.
209 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);
212 * Get the timer base before entering C state
214 timer = acpi_hw_pmt_ticks ();
217 * Enter C3:
218 * ---------
219 * Read from the P_LVL3 (P_BLK+5) register to invoke a C3 transition.
221 acpi_os_in8 ((ACPI_IO_ADDRESS)(pblk_address + 5));
224 * Perform Dummy Op:
225 * -----------------
226 * We have to do something useless after reading LVL3 because chipsets
227 * cannot guarantee that STPCLK# gets asserted in time to freeze execution.
229 acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
231 * Immediately compute the time in the C state
233 timer = acpi_hw_pmt_ticks() - timer;
236 * Re-Enable Bus Mastering:
237 * ------------------------
238 * Clear the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits.
240 acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0);
242 /* TBD: [Unhandled]: Support 24-bit timers (this algorithm assumes 32-bit) */
244 *pm_timer_ticks = timer;
247 * Re-enable interrupts after coming out of C2/C3.
249 enable();
251 return (AE_OK);
255 /****************************************************************************
257 * FUNCTION: Acpi_hw_enter_cx
259 * PARAMETERS: Processor_handle - handle of the processor
261 * RETURN: Status of function
263 * DESCRIPTION: Invoke the currently active processor Cx handler to put this
264 * processor to sleep.
266 ****************************************************************************/
268 ACPI_STATUS
269 acpi_hw_enter_cx (
270 ACPI_IO_ADDRESS pblk_address,
271 u32 *pm_timer_ticks)
274 if (!acpi_hw_cx_handlers[acpi_hw_active_cx_state]) {
275 return (AE_SUPPORT);
278 return (acpi_hw_cx_handlers[acpi_hw_active_cx_state] (pblk_address, pm_timer_ticks));
282 /****************************************************************************
284 * FUNCTION: Acpi_hw_set_cx
286 * PARAMETERS: State - value (1-3) of the Cx state to 'make active'
288 * RETURN: Function status.
290 * DESCRIPTION: Sets the state to use during calls to Acpi_hw_enter_cx().
292 ****************************************************************************/
294 ACPI_STATUS
295 acpi_hw_set_cx (
296 u32 cx_state)
299 * Supported State?
300 * ----------------
302 if ((cx_state < 1) || (cx_state > 3)) {
303 return (AE_BAD_PARAMETER);
306 if (!acpi_hw_cx_handlers[cx_state]) {
307 return (AE_SUPPORT);
311 * New Cx State?
312 * -------------
313 * We only care when moving from one state to another...
315 if (acpi_hw_active_cx_state == cx_state) {
316 return (AE_OK);
320 * Prepare to Use New State:
321 * -------------------------
322 * If the new Cx_state is C3, the BM_RLD bit must be set to allow
323 * the generation of a bus master requets to cause the processor
324 * in the C3 state to transition to the C0 state.
326 switch (cx_state)
328 case 3:
329 acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1);
330 break;
334 * Clean up from Old State:
335 * ------------------------
336 * If the old Cx_state was C3, the BM_RLD bit is reset. When the
337 * bit is reset, the generation of a bus master request does not
338 * effect any processor in the C3 state.
340 switch (acpi_hw_active_cx_state)
342 case 3:
343 acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0);
344 break;
348 * Enable:
349 * -------
351 acpi_hw_active_cx_state = cx_state;
353 return (AE_OK);
357 /****************************************************************************
359 * FUNCTION: Acpi_hw_get_cx_info
361 * PARAMETERS: Cx_states - Information (latencies) on all Cx states
363 * RETURN: Status of function
365 * DESCRIPTION: This function is called both to initialize Cx handling
366 * and retrieve the current Cx information (latency values).
368 ****************************************************************************/
370 ACPI_STATUS
371 acpi_hw_get_cx_info (
372 u32 cx_states[])
374 u8 SMP_system = FALSE;
377 if (!cx_states) {
378 return(AE_BAD_PARAMETER);
382 * TBD: [Unhandled] need to init SMP_system using info from the MAPIC
383 * table.
387 * Set Defaults:
388 * -------------
389 * C0 and C1 support is implied (but what about that PROC_C1 register
390 * in the FADT?!?!). Set C2/C3 to max. latency (not supported until
391 * proven otherwise).
393 cx_states[0] = 0;
394 cx_states[1] = 0;
395 cx_states[2] = MAX_CX_STATE_LATENCY;
396 cx_states[3] = MAX_CX_STATE_LATENCY;
399 * C2 Supported?
400 * -------------
401 * We're only supporting C2 when the latency is <= 100 microseconds,
402 * and on SMP systems when P_LVL2_UP (which indicates C2 only on UP)
403 * is not set.
405 if (acpi_gbl_FADT->plvl2_lat <= 100) {
406 if (!SMP_system) {
407 acpi_hw_cx_handlers[2] = acpi_hw_enter_c2;
408 cx_states[2] = acpi_gbl_FADT->plvl2_lat;
411 else if (!acpi_gbl_FADT->plvl2_up) {
412 acpi_hw_cx_handlers[2] = acpi_hw_enter_c2;
413 cx_states[2] = acpi_gbl_FADT->plvl2_lat;
418 * C3 Supported?
419 * -------------
420 * We're only supporting C3 on UP systems when the latency is
421 * <= 1000 microseconds and that include the ability to disable
422 * Bus Mastering while in C3 (ARB_DIS) but allows Bus Mastering
423 * requests to wake the system from C3 (BM_RLD). Note his method
424 * of maintaining cache coherency (disabling of bus mastering)
425 * cannot be used on SMP systems, and flushing caches (e.g. WBINVD)
426 * is simply too costly (at this time).
428 if (acpi_gbl_FADT->plvl3_lat <= 1000) {
429 if (!SMP_system && (acpi_gbl_FADT->Xpm2_cnt_blk.address &&
430 acpi_gbl_FADT->pm2_cnt_len))
432 acpi_hw_cx_handlers[3] = acpi_hw_enter_c3;
433 cx_states[3] = acpi_gbl_FADT->plvl3_lat;
437 return(AE_OK);
441 /****************************************************************************
443 * FUNCTION: Acpi_hw_get_cx_handler
445 * PARAMETERS: State - the Cx state
446 * Handler - pointer to location for the returned handler
448 * RETURN: Status of function
450 * DESCRIPTION: This function is called to get an installed Cx state handler.
452 ****************************************************************************/
454 ACPI_STATUS
455 acpi_hw_get_cx_handler (
456 u32 cx_state,
457 ACPI_C_STATE_HANDLER *handler)
460 if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) {
461 return(AE_BAD_PARAMETER);
464 *handler = acpi_hw_cx_handlers[cx_state];
466 return(AE_OK);
470 /****************************************************************************
472 * FUNCTION: Acpi_hw_set_cx_handler
474 * PARAMETERS: Cx_state - the Cx state
475 * Handler - new Cx state handler
477 * RETURN: Status of function
479 * DESCRIPTION: This function is called to install a new Cx state handler.
481 ****************************************************************************/
483 ACPI_STATUS
484 acpi_hw_set_cx_handler (
485 u32 cx_state,
486 ACPI_C_STATE_HANDLER handler)
489 if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) {
490 return(AE_BAD_PARAMETER);
493 acpi_hw_cx_handlers[cx_state] = handler;
495 return(AE_OK);
499 /**************************************************************************
501 * FUNCTION: Acpi_hw_local_pow
503 * PARAMETERS: x,y operands
505 * RETURN: result
507 * DESCRIPTION: Compute x ^ y
509 *************************************************************************/
511 NATIVE_UINT
512 acpi_hw_local_pow (
513 NATIVE_UINT x,
514 NATIVE_UINT y)
516 NATIVE_UINT i;
517 NATIVE_UINT result = 1;
520 for (i = 0; i < y; i++) {
521 result = result * x;
524 return (result);
528 /**************************************************************************
530 * FUNCTION: Acpi_hw_enable_throttling
532 * PARAMETERS: Pblk_address - Address of Pcnt (Processor Control)
533 * register
535 * RETURN: none
537 * DESCRIPTION: Enable throttling by setting the THT_EN bit.
539 *************************************************************************/
541 void
542 acpi_hw_enable_throttling (
543 ACPI_IO_ADDRESS pblk_address)
545 u32 pblk_value;
548 pblk_value = acpi_os_in32 (pblk_address);
549 pblk_value = pblk_value | BIT_4;
550 acpi_os_out32 (pblk_address, pblk_value);
552 return;
556 /**************************************************************************
558 * FUNCTION: Acpi_hw_disable_throttling
560 * PARAMETERS: Pblk_address - Address of Pcnt (Processor Control)
561 * register
563 * RETURN: none
565 * DESCRIPTION:Disable throttling by clearing the THT_EN bit
567 *************************************************************************/
569 void
570 acpi_hw_disable_throttling (
571 ACPI_IO_ADDRESS pblk_address)
573 u32 pblk_value;
576 pblk_value = acpi_os_in32 (pblk_address);
577 pblk_value = pblk_value & (~(u32)BIT_4);
578 acpi_os_out32 (pblk_address, pblk_value);
580 return;
584 /**************************************************************************
586 * FUNCTION: Acpi_hw_get_duty_cycle
588 * PARAMETERS: Duty_offset Pcnt register duty cycle field offset
589 * Pblk_address Pcnt register address in chipset
590 * Num_throttle_states # of CPU throttle states this system
591 * supports
593 * RETURN: none
595 * DESCRIPTION: Get the duty cycle from the chipset
597 *************************************************************************/
600 acpi_hw_get_duty_cycle (
601 u8 duty_offset,
602 ACPI_IO_ADDRESS pblk_address,
603 u32 num_throttle_states)
605 NATIVE_UINT index;
606 u32 duty32_value;
607 u32 pcnt_mask_off_duty_field;
611 * Use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)]
612 * and then shift it into the right position
614 pcnt_mask_off_duty_field = num_throttle_states - 1;
617 * Read in the current value from the port
619 duty32_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address);
622 * Shift the the value to LSB
624 for (index = 0; index < (NATIVE_UINT) duty_offset; index++) {
625 duty32_value = duty32_value >> 1;
629 * Get the duty field only
631 duty32_value = duty32_value & pcnt_mask_off_duty_field;
633 return ((u32) duty32_value);
637 /**************************************************************************
639 * FUNCTION: Acpi_hw_program_duty_cycle
641 * PARAMETERS: Duty_offset Pcnt register duty cycle field offset
642 * Duty_cycle duty cycle to program into chipset
643 * Pblk_address Pcnt register address in chipset
644 * Num_throttle_states # of CPU throttle states this system
645 * supports
647 * RETURN: none
649 * DESCRIPTION: Program chipset with specified duty cycle by bit-shifting the
650 * duty cycle bits to the appropriate offset, reading the duty
651 * cycle register, OR-ing in the duty cycle, and writing it to
652 * the Pcnt register.
654 *************************************************************************/
656 void
657 acpi_hw_program_duty_cycle (
658 u8 duty_offset,
659 u32 duty_cycle,
660 ACPI_IO_ADDRESS pblk_address,
661 u32 num_throttle_states)
663 NATIVE_UINT index;
664 u32 duty32_value;
665 u32 pcnt_mask_off_duty_field;
666 u32 port_value;
670 * valid Duty_cycle passed
672 duty32_value = duty_cycle;
675 * use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)]
676 * and then shift it into the right position
678 pcnt_mask_off_duty_field = num_throttle_states - 1;
681 * Shift the mask
683 for (index = 0; index < (NATIVE_UINT) duty_offset; index++) {
684 pcnt_mask_off_duty_field = pcnt_mask_off_duty_field << 1;
685 duty32_value = duty32_value << 1;
689 * Read in the current value from the port
691 port_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address);
694 * Mask off the duty field so we don't OR in junk!
696 port_value = port_value & (~pcnt_mask_off_duty_field);
699 * OR in the bits we want to write out to the port
701 port_value = (port_value | duty32_value) & (~(u32)BIT_4);
704 * write it to the port
706 acpi_os_out32 ((ACPI_IO_ADDRESS) pblk_address, port_value);
708 return;