Merge branch 'fluff' into release
[linux-2.6] / drivers / acpi / acpica / hwregs.c
1
2 /*******************************************************************************
3  *
4  * Module Name: hwregs - Read/write access functions for the various ACPI
5  *                       control and status registers.
6  *
7  ******************************************************************************/
8
9 /*
10  * Copyright (C) 2000 - 2008, Intel Corp.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions, and the following disclaimer,
18  *    without modification.
19  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20  *    substantially similar to the "NO WARRANTY" disclaimer below
21  *    ("Disclaimer") and any redistribution must be conditioned upon
22  *    including a substantially similar Disclaimer requirement for further
23  *    binary redistribution.
24  * 3. Neither the names of the above-listed copyright holders nor the names
25  *    of any contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * Alternatively, this software may be distributed under the terms of the
29  * GNU General Public License ("GPL") version 2 as published by the Free
30  * Software Foundation.
31  *
32  * NO WARRANTY
33  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43  * POSSIBILITY OF SUCH DAMAGES.
44  */
45
46 #include <acpi/acpi.h>
47 #include "accommon.h"
48 #include "acnamesp.h"
49 #include "acevents.h"
50
51 #define _COMPONENT          ACPI_HARDWARE
52 ACPI_MODULE_NAME("hwregs")
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_hw_clear_acpi_status
57  *
58  * PARAMETERS:  None
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Clears all fixed and general purpose status bits
63  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
64  *
65  ******************************************************************************/
66 acpi_status acpi_hw_clear_acpi_status(void)
67 {
68         acpi_status status;
69         acpi_cpu_flags lock_flags = 0;
70
71         ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
72
73         ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
74                           ACPI_BITMASK_ALL_FIXED_STATUS,
75                           (u16) acpi_gbl_FADT.xpm1a_event_block.address));
76
77         lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
78
79         status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
80                                         ACPI_BITMASK_ALL_FIXED_STATUS);
81         if (ACPI_FAILURE(status)) {
82                 goto unlock_and_exit;
83         }
84
85         /* Clear the fixed events */
86
87         if (acpi_gbl_FADT.xpm1b_event_block.address) {
88                 status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS,
89                                     &acpi_gbl_FADT.xpm1b_event_block);
90                 if (ACPI_FAILURE(status)) {
91                         goto unlock_and_exit;
92                 }
93         }
94
95         /* Clear the GPE Bits in all GPE registers in all GPE blocks */
96
97         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
98
99       unlock_and_exit:
100         acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
101         return_ACPI_STATUS(status);
102 }
103
104 /*******************************************************************************
105  *
106  * FUNCTION:    acpi_hw_get_register_bit_mask
107  *
108  * PARAMETERS:  register_id         - Index of ACPI Register to access
109  *
110  * RETURN:      The bitmask to be used when accessing the register
111  *
112  * DESCRIPTION: Map register_id into a register bitmask.
113  *
114  ******************************************************************************/
115
116 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
117 {
118         ACPI_FUNCTION_ENTRY();
119
120         if (register_id > ACPI_BITREG_MAX) {
121                 ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
122                             register_id));
123                 return (NULL);
124         }
125
126         return (&acpi_gbl_bit_register_info[register_id]);
127 }
128
129 /******************************************************************************
130  *
131  * FUNCTION:    acpi_hw_register_read
132  *
133  * PARAMETERS:  register_id         - ACPI Register ID
134  *              return_value        - Where the register value is returned
135  *
136  * RETURN:      Status and the value read.
137  *
138  * DESCRIPTION: Read from the specified ACPI register
139  *
140  ******************************************************************************/
141 acpi_status
142 acpi_hw_register_read(u32 register_id, u32 * return_value)
143 {
144         u32 value1 = 0;
145         u32 value2 = 0;
146         acpi_status status;
147
148         ACPI_FUNCTION_TRACE(hw_register_read);
149
150         switch (register_id) {
151         case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
152
153                 status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block);
154                 if (ACPI_FAILURE(status)) {
155                         goto exit;
156                 }
157
158                 /* PM1B is optional */
159
160                 status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block);
161                 value1 |= value2;
162                 break;
163
164         case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
165
166                 status = acpi_read(&value1, &acpi_gbl_xpm1a_enable);
167                 if (ACPI_FAILURE(status)) {
168                         goto exit;
169                 }
170
171                 /* PM1B is optional */
172
173                 status = acpi_read(&value2, &acpi_gbl_xpm1b_enable);
174                 value1 |= value2;
175                 break;
176
177         case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
178
179                 status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block);
180                 if (ACPI_FAILURE(status)) {
181                         goto exit;
182                 }
183
184                 status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block);
185                 value1 |= value2;
186                 break;
187
188         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
189
190                 status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block);
191                 break;
192
193         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
194
195                 status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block);
196                 break;
197
198         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
199
200                 status =
201                     acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
202                 break;
203
204         default:
205                 ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
206                 status = AE_BAD_PARAMETER;
207                 break;
208         }
209
210       exit:
211
212         if (ACPI_SUCCESS(status)) {
213                 *return_value = value1;
214         }
215
216         return_ACPI_STATUS(status);
217 }
218
219 /******************************************************************************
220  *
221  * FUNCTION:    acpi_hw_register_write
222  *
223  * PARAMETERS:  register_id         - ACPI Register ID
224  *              Value               - The value to write
225  *
226  * RETURN:      Status
227  *
228  * DESCRIPTION: Write to the specified ACPI register
229  *
230  * NOTE: In accordance with the ACPI specification, this function automatically
231  * preserves the value of the following bits, meaning that these bits cannot be
232  * changed via this interface:
233  *
234  * PM1_CONTROL[0] = SCI_EN
235  * PM1_CONTROL[9]
236  * PM1_STATUS[11]
237  *
238  * ACPI References:
239  * 1) Hardware Ignored Bits: When software writes to a register with ignored
240  *      bit fields, it preserves the ignored bit fields
241  * 2) SCI_EN: OSPM always preserves this bit position
242  *
243  ******************************************************************************/
244
245 acpi_status acpi_hw_register_write(u32 register_id, u32 value)
246 {
247         acpi_status status;
248         u32 read_value;
249
250         ACPI_FUNCTION_TRACE(hw_register_write);
251
252         switch (register_id) {
253         case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
254
255                 /* Perform a read first to preserve certain bits (per ACPI spec) */
256
257                 status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
258                                                &read_value);
259                 if (ACPI_FAILURE(status)) {
260                         goto exit;
261                 }
262
263                 /* Insert the bits to be preserved */
264
265                 ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
266                                  read_value);
267
268                 /* Now we can write the data */
269
270                 status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block);
271                 if (ACPI_FAILURE(status)) {
272                         goto exit;
273                 }
274
275                 /* PM1B is optional */
276
277                 status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block);
278                 break;
279
280         case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
281
282                 status = acpi_write(value, &acpi_gbl_xpm1a_enable);
283                 if (ACPI_FAILURE(status)) {
284                         goto exit;
285                 }
286
287                 /* PM1B is optional */
288
289                 status = acpi_write(value, &acpi_gbl_xpm1b_enable);
290                 break;
291
292         case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
293
294                 /*
295                  * Perform a read first to preserve certain bits (per ACPI spec)
296                  */
297                 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
298                                                &read_value);
299                 if (ACPI_FAILURE(status)) {
300                         goto exit;
301                 }
302
303                 /* Insert the bits to be preserved */
304
305                 ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
306                                  read_value);
307
308                 /* Now we can write the data */
309
310                 status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block);
311                 if (ACPI_FAILURE(status)) {
312                         goto exit;
313                 }
314
315                 status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block);
316                 break;
317
318         case ACPI_REGISTER_PM1A_CONTROL:        /* 16-bit access */
319
320                 status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block);
321                 break;
322
323         case ACPI_REGISTER_PM1B_CONTROL:        /* 16-bit access */
324
325                 status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block);
326                 break;
327
328         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
329
330                 status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block);
331                 break;
332
333         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
334
335                 status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block);
336                 break;
337
338         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
339
340                 /* SMI_CMD is currently always in IO space */
341
342                 status =
343                     acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
344                 break;
345
346         default:
347                 status = AE_BAD_PARAMETER;
348                 break;
349         }
350
351       exit:
352         return_ACPI_STATUS(status);
353 }