]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/acpi/tables/tbfadt.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6-omap-h63xx.git] / drivers / acpi / tables / tbfadt.c
index 1285e91474fbff4c504d82e75ebe9b63c608eb24..2c7885e7ffba6c06508e261f5ef547819661db51 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2007, R. Byron Moore
+ * Copyright (C) 2000 - 2008, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt")
 /* Local prototypes */
 static void inline
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
-                            u8 bit_width, u64 address);
+                            u8 byte_width, u64 address);
 
 static void acpi_tb_convert_fadt(void);
 
@@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
  * FUNCTION:    acpi_tb_init_generic_address
  *
  * PARAMETERS:  generic_address     - GAS struct to be initialized
- *              bit_width           - Width of this register
+ *              byte_width          - Width of this register
  *              Address             - Address of the register
  *
  * RETURN:      None
@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
 
 static void inline
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
-                            u8 bit_width, u64 address)
+                            u8 byte_width, u64 address)
 {
 
        /*
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
        /* All other fields are byte-wide */
 
        generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
-       generic_address->bit_width = bit_width;
+       generic_address->bit_width = byte_width << 3;
        generic_address->bit_offset = 0;
        generic_address->access_width = 0;
 }
@@ -155,7 +155,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
  *
  ******************************************************************************/
 
-void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
+void acpi_tb_parse_fadt(u32 table_index, u8 flags)
 {
        u32 length;
        struct acpi_table_header *table;
@@ -211,14 +211,17 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
  * DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
  *              Performs validation on some important FADT fields.
  *
+ * NOTE:        We create a local copy of the FADT regardless of the version.
+ *
  ******************************************************************************/
 
 void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
 {
 
        /*
-        * Check if the FADT is larger than what we know about (ACPI 2.0 version).
-        * Truncate the table, but make some noise.
+        * Check if the FADT is larger than the largest table that we expect
+        * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
+        * a warning.
         */
        if (length > sizeof(struct acpi_table_fadt)) {
                ACPI_WARNING((AE_INFO,
@@ -227,10 +230,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
                              sizeof(struct acpi_table_fadt)));
        }
 
-       /* Copy the entire FADT locally. Zero first for tb_convert_fadt */
+       /* Clear the entire local FADT */
 
        ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));
 
+       /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */
+
        ACPI_MEMCPY(&acpi_gbl_FADT, table,
                    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));
 
@@ -251,7 +256,7 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
  * RETURN:      None
  *
  * DESCRIPTION: Converts all versions of the FADT to a common internal format.
- *              -> Expand all 32-bit addresses to 64-bit.
+ *              Expand all 32-bit addresses to 64-bit.
  *
  * NOTE:        acpi_gbl_FADT must be of size (struct acpi_table_fadt),
  *              and must contain a copy of the actual FADT.
@@ -275,7 +280,7 @@ static void acpi_tb_convert_fadt(void)
 {
        u8 pm1_register_length;
        struct acpi_generic_address *target;
-       acpi_native_uint i;
+       u32 i;
 
        /* Update the local FADT table header length */
 
@@ -292,8 +297,23 @@ static void acpi_tb_convert_fadt(void)
        }
 
        /*
-        * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address
-        * structures as necessary.
+        * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
+        * should be zero are indeed zero. This will workaround BIOSs that
+        * inadvertently place values in these fields.
+        *
+        * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at
+        * offset 45, 55, 95, and the word located at offset 109, 110.
+        */
+       if (acpi_gbl_FADT.header.revision < 3) {
+               acpi_gbl_FADT.preferred_profile = 0;
+               acpi_gbl_FADT.pstate_control = 0;
+               acpi_gbl_FADT.cst_control = 0;
+               acpi_gbl_FADT.boot_flags = 0;
+       }
+
+       /*
+        * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X"
+        * generic address structures as necessary.
         */
        for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
                target =
@@ -322,9 +342,20 @@ static void acpi_tb_convert_fadt(void)
         * useful to calculate them once, here.
         *
         * The PM event blocks are split into two register blocks, first is the
-        * PM Status Register block, followed immediately by the PM Enable Register
-        * block. Each is of length (pm1_event_length/2)
+        * PM Status Register block, followed immediately by the PM Enable
+        * Register block. Each is of length (xpm1x_event_block.bit_width/2).
+        *
+        * On various systems the v2 fields (and particularly the bit widths)
+        * cannot be relied upon, though. Hence resort to using the v1 length
+        * here (and warn about the inconsistency).
         */
+       if (acpi_gbl_FADT.xpm1a_event_block.bit_width
+           != acpi_gbl_FADT.pm1_event_length * 8)
+               printk(KERN_WARNING "FADT: "
+                      "X_PM1a_EVT_BLK.bit_width (%u) does not match"
+                      " PM1_EVT_LEN (%u)\n",
+                      acpi_gbl_FADT.xpm1a_event_block.bit_width,
+                      acpi_gbl_FADT.pm1_event_length);
        pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
 
        /* The PM1A register block is required */
@@ -340,26 +371,21 @@ static void acpi_tb_convert_fadt(void)
        /* The PM1B register block is optional, ignore if not present */
 
        if (acpi_gbl_FADT.xpm1b_event_block.address) {
+               if (acpi_gbl_FADT.xpm1b_event_block.bit_width
+                   != acpi_gbl_FADT.pm1_event_length * 8)
+                       printk(KERN_WARNING "FADT: "
+                              "X_PM1b_EVT_BLK.bit_width (%u) does not match"
+                              " PM1_EVT_LEN (%u)\n",
+                              acpi_gbl_FADT.xpm1b_event_block.bit_width,
+                              acpi_gbl_FADT.pm1_event_length);
                acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
                                             pm1_register_length,
                                             (acpi_gbl_FADT.xpm1b_event_block.
                                              address + pm1_register_length));
                /* Don't forget to copy space_id of the GAS */
                acpi_gbl_xpm1b_enable.space_id =
-                   acpi_gbl_FADT.xpm1a_event_block.space_id;
-
-       }
+                   acpi_gbl_FADT.xpm1b_event_block.space_id;
 
-       /*
-        * For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero)
-        * are indeed zero. This will workaround BIOSs that inadvertently placed
-        * values in these fields.
-        */
-       if (acpi_gbl_FADT.header.revision < 3) {
-               acpi_gbl_FADT.preferred_profile = 0;
-               acpi_gbl_FADT.pstate_control = 0;
-               acpi_gbl_FADT.cst_control = 0;
-               acpi_gbl_FADT.boot_flags = 0;
        }
 }
 
@@ -388,7 +414,7 @@ static void acpi_tb_validate_fadt(void)
        u32 *address32;
        struct acpi_generic_address *address64;
        u8 length;
-       acpi_native_uint i;
+       u32 i;
 
        /* Examine all of the 64-bit extended address fields (X fields) */