diff options
Diffstat (limited to 'drivers/acpi/hardware')
-rw-r--r-- | drivers/acpi/hardware/hwacpi.c | 52 | ||||
-rw-r--r-- | drivers/acpi/hardware/hwgpe.c | 5 | ||||
-rw-r--r-- | drivers/acpi/hardware/hwregs.c | 57 | ||||
-rw-r--r-- | drivers/acpi/hardware/hwsleep.c | 189 | ||||
-rw-r--r-- | drivers/acpi/hardware/hwtimer.c | 196 |
5 files changed, 413 insertions, 86 deletions
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index d2154a1a2..304d3dec6 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c @@ -1,12 +1,13 @@ + /****************************************************************************** * - * Module Name: hwacpi - ACPI hardware functions - mode and timer - * $Revision: 34 $ + * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface + * $Revision: 36 $ * *****************************************************************************/ /* - * Copyright (C) 2000 R. Byron Moore + * Copyright (C) 2000, 2001 R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -304,48 +305,3 @@ acpi_hw_get_mode_capabilities (void) } -/****************************************************************************** - * - * FUNCTION: Acpi_hw_pmt_ticks - * - * PARAMETERS: none - * - * RETURN: Current value of the ACPI PMT (timer) - * - * DESCRIPTION: Obtains current value of ACPI PMT - * - ******************************************************************************/ - -u32 -acpi_hw_pmt_ticks (void) -{ - u32 ticks; - - ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)); - - return (ticks); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_hw_pmt_resolution - * - * PARAMETERS: none - * - * RETURN: Number of bits of resolution in the PMT (either 24 or 32) - * - * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit) - * - ******************************************************************************/ - -u32 -acpi_hw_pmt_resolution (void) -{ - if (0 == acpi_gbl_FADT->tmr_val_ext) { - return (24); - } - - return (32); -} - diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index 2b413fac8..b7b777df6 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -1,12 +1,13 @@ + /****************************************************************************** * * Module Name: hwgpe - Low level GPE enable/disable/clear functions - * $Revision: 25 $ + * $Revision: 28 $ * *****************************************************************************/ /* - * Copyright (C) 2000 R. Byron Moore + * Copyright (C) 2000, 2001 R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 77b6a1c8c..fc96c51fb 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -3,12 +3,12 @@ * * Module Name: hwregs - Read/write access functions for the various ACPI * control and status registers. - * $Revision: 86 $ + * $Revision: 88 $ * ******************************************************************************/ /* - * Copyright (C) 2000 R. Byron Moore + * Copyright (C) 2000, 2001 R. Byron Moore * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,7 +37,7 @@ /* This matches the #defines in actypes.h. */ NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_", - "\\_S4_","\\_S4_b","\\_S5_"}; + "\\_S4_","\\_S5_","\\_S4_b"}; /******************************************************************************* @@ -53,7 +53,7 @@ NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_"," * ******************************************************************************/ -static u32 +u32 acpi_hw_get_bit_shift ( u32 mask) { @@ -185,9 +185,9 @@ acpi_hw_obtain_sleep_type_register_data ( } else if (((obj_desc->package.elements[0])->common.type != - ACPI_TYPE_NUMBER) || + ACPI_TYPE_INTEGER) || ((obj_desc->package.elements[1])->common.type != - ACPI_TYPE_NUMBER)) + ACPI_TYPE_INTEGER)) { /* Must have two */ @@ -199,9 +199,9 @@ acpi_hw_obtain_sleep_type_register_data ( /* * Valid _Sx_ package size, type, and value */ - *slp_typ_a = (u8) (obj_desc->package.elements[0])->number.value; + *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value; - *slp_typ_b = (u8) (obj_desc->package.elements[1])->number.value; + *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value; } @@ -581,13 +581,8 @@ acpi_hw_register_read ( case PM1_CONTROL: /* 16-bit access */ - if (register_id != SLP_TYPE_B) { - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - } - - if (register_id != SLP_TYPE_A) { - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); - } + value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; @@ -696,30 +691,20 @@ acpi_hw_register_write ( case PM1_CONTROL: /* 16-bit access */ - /* - * If SLP_TYP_A or SLP_TYP_B, only write to one reg block. - * Otherwise, write to both. - */ - if (register_id == SLP_TYPE_A) { - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - } - else if (register_id == SLP_TYPE_B) { - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); - } - else { - /* disable/re-enable interrupts if sleeping */ - if (register_id == SLP_EN) { - disable(); - } + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + break; - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); - if (register_id == SLP_EN) { - enable(); - } - } + case PM1_a_CONTROL: /* 16-bit access */ + + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + break; + + + case PM1_b_CONTROL: /* 16-bit access */ + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c new file mode 100644 index 000000000..892c721c6 --- /dev/null +++ b/drivers/acpi/hardware/hwsleep.c @@ -0,0 +1,189 @@ + +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * $Revision: 5 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "acnamesp.h" +#include "achware.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwsleep") + + +/****************************************************************************** + * + * FUNCTION: Acpi_set_firmware_waking_vector + * + * PARAMETERS: Physical_address - Physical address of ACPI real mode + * entry point. + * + * RETURN: AE_OK or AE_ERROR + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_set_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS physical_address) +{ + + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Set the vector */ + + if (acpi_gbl_FACS->vector_width == 32) { + * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address; + } + else { + *acpi_gbl_FACS->firmware_waking_vector = physical_address; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_firmware_waking_vector + * + * PARAMETERS: *Physical_address - Output buffer where contents of + * the Firmware_waking_vector field of + * the FACS will be stored. + * + * RETURN: Status + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS *physical_address) +{ + + + if (!physical_address) { + return (AE_BAD_PARAMETER); + } + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Get the vector */ + + if (acpi_gbl_FACS->vector_width == 32) { + *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector; + } + else { + *physical_address = *acpi_gbl_FACS->firmware_waking_vector; + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: Acpi_enter_sleep_state + * + * PARAMETERS: Sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enter_sleep_state ( + u8 sleep_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg; + u8 type_a; + u8 type_b; + u16 PM1_acontrol; + u16 PM1_bcontrol; + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + + status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b); + + if (!ACPI_SUCCESS(status)) { + return status; + } + + /* run the _PTS and _GTS methods */ + MEMSET(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + MEMSET(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); + acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL); + + /* clear wake status */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); + + PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL); + + /* mask off SLP_EN and SLP_TYP fields */ + PM1_acontrol &= 0xC3FF; + + /* mask in SLP_EN */ + PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); + + PM1_bcontrol = PM1_acontrol; + + /* mask in SLP_TYP */ + PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + + /* the old version was disabling interrupts. let's try it without + * and see how that works + */ + /*disable();*/ + + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol); + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol); + + /*enable();*/ + + return (AE_OK); +} diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c new file mode 100644 index 000000000..b7f529ccf --- /dev/null +++ b/drivers/acpi/hardware/hwtimer.c @@ -0,0 +1,196 @@ + +/****************************************************************************** + * + * Name: hwtimer.c - ACPI Power Management Timer Interface + * $Revision: 4 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "achware.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwtimer") + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer_resolution + * + * PARAMETERS: none + * + * RETURN: Number of bits of resolution in the PM Timer (24 or 32). + * + * DESCRIPTION: Obtains resolution of the ACPI PM Timer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer_resolution ( + u32 *resolution) +{ + if (!resolution) { + return (AE_BAD_PARAMETER); + } + + if (0 == acpi_gbl_FADT->tmr_val_ext) { + *resolution = 24; + } + else { + *resolution = 32; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer + * + * PARAMETERS: none + * + * RETURN: Current value of the ACPI PM Timer (in ticks). + * + * DESCRIPTION: Obtains current value of ACPI PM Timer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer ( + u32 *ticks) +{ + if (!ticks) { + return (AE_BAD_PARAMETER); + } + + *ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer_duration + * + * PARAMETERS: Start_ticks + * End_ticks + * Time_elapsed + * + * RETURN: Time_elapsed + * + * DESCRIPTION: Computes the time elapsed (in microseconds) between two + * PM Timer time stamps, taking into account the possibility of + * rollovers, the timer resolution, and timer frequency. + * + * The PM Timer's clock ticks at roughly 3.6 times per + * _microsecond_, and its clock continues through Cx state + * transitions (unlike many CPU timestamp counters) -- making it + * a versatile and accurate timer. + * + * Note that this function accomodates only a single timer + * rollover. Thus for 24-bit timers, this function should only + * be used for calculating durations less than ~4.6 seconds + * (~20 hours for 32-bit timers). + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer_duration ( + u32 start_ticks, + u32 end_ticks, + u32 *time_elapsed) +{ + u32 delta_ticks = 0; + u32 seconds = 0; + u32 milliseconds = 0; + u32 microseconds = 0; + u32 remainder = 0; + + if (!time_elapsed) { + return (AE_BAD_PARAMETER); + } + + /* + * Compute Tick Delta: + * ------------------- + * Handle timer rollovers on 24- versus 32-bit timers. + */ + if (start_ticks < end_ticks) { + delta_ticks = end_ticks - start_ticks; + } + else if (start_ticks > end_ticks) { + /* 24-bit Timer */ + if (0 == acpi_gbl_FADT->tmr_val_ext) { + delta_ticks = (0x00FFFFFF - start_ticks) + end_ticks; + } + /* 32-bit Timer */ + else { + delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; + } + } + + /* + * Compute Duration: + * ----------------- + * Since certain compilers (gcc/Linux, argh!) don't support 64-bit + * divides in kernel-space we have to do some trickery to preserve + * accuracy while using 32-bit math. + * + * TODO: Change to use 64-bit math when supported. + * + * The process is as follows: + * 1. Compute the number of seconds by dividing Delta Ticks by + * the timer frequency. + * 2. Compute the number of milliseconds in the remainder from step #1 + * by multiplying by 1000 and then dividing by the timer frequency. + * 3. Compute the number of microseconds in the remainder from step #2 + * by multiplying by 1000 and then dividing by the timer frequency. + * 4. Add the results from steps 1, 2, and 3 to get the total duration. + * + * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be + * 1199864031 microseconds. This is computed as follows: + * Step #1: Seconds = 1199; Remainder = 3092840 + * Step #2: Milliseconds = 864; Remainder = 113120 + * Step #3: Microseconds = 31; Remainder = <don't care!> + */ + + /* Step #1 */ + seconds = delta_ticks / PM_TIMER_FREQUENCY; + remainder = delta_ticks % PM_TIMER_FREQUENCY; + + /* Step #2 */ + milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; + remainder = (remainder * 1000) % PM_TIMER_FREQUENCY; + + /* Step #3 */ + microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; + + /* Step #4 */ + *time_elapsed = seconds * 1000000; + *time_elapsed += milliseconds * 1000; + *time_elapsed += microseconds; + + return (AE_OK); +} + + |