fa58c1edce1e52f00c6b1cecebbe3f63a7a4af6f
[sfrench/cifs-2.6.git] / drivers / acpi / hardware / 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 - 2006, R. Byron Moore
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 <acpi/acnamesp.h>
48 #include <acpi/acevents.h>
49
50 #define _COMPONENT          ACPI_HARDWARE
51 ACPI_MODULE_NAME("hwregs")
52
53 /*******************************************************************************
54  *
55  * FUNCTION:    acpi_hw_clear_acpi_status
56  *
57  * PARAMETERS:  Flags           - Lock the hardware or not
58  *
59  * RETURN:      none
60  *
61  * DESCRIPTION: Clears all fixed and general purpose status bits
62  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
63  *
64  * NOTE: TBD: Flags parameter is obsolete, to be removed
65  *
66  ******************************************************************************/
67 acpi_status acpi_hw_clear_acpi_status(u32 flags)
68 {
69         acpi_status status;
70         acpi_cpu_flags lock_flags = 0;
71
72         ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
73
74         ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
75                           ACPI_BITMASK_ALL_FIXED_STATUS,
76                           (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
77
78         lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
79
80         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
81                                         ACPI_REGISTER_PM1_STATUS,
82                                         ACPI_BITMASK_ALL_FIXED_STATUS);
83         if (ACPI_FAILURE(status)) {
84                 goto unlock_and_exit;
85         }
86
87         /* Clear the fixed events */
88
89         if (acpi_gbl_FADT->xpm1b_evt_blk.address) {
90                 status =
91                     acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
92                                             &acpi_gbl_FADT->xpm1b_evt_blk);
93                 if (ACPI_FAILURE(status)) {
94                         goto unlock_and_exit;
95                 }
96         }
97
98         /* Clear the GPE Bits in all GPE registers in all GPE blocks */
99
100         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
101
102       unlock_and_exit:
103         acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
104         return_ACPI_STATUS(status);
105 }
106
107 /*******************************************************************************
108  *
109  * FUNCTION:    acpi_get_sleep_type_data
110  *
111  * PARAMETERS:  sleep_state         - Numeric sleep state
112  *              *sleep_type_a        - Where SLP_TYPa is returned
113  *              *sleep_type_b        - Where SLP_TYPb is returned
114  *
115  * RETURN:      Status - ACPI status
116  *
117  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
118  *              state.
119  *
120  ******************************************************************************/
121
122 acpi_status
123 acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
124 {
125         acpi_status status = AE_OK;
126         struct acpi_evaluate_info *info;
127
128         ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
129
130         /* Validate parameters */
131
132         if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
133                 return_ACPI_STATUS(AE_BAD_PARAMETER);
134         }
135
136         /* Allocate the evaluation information block */
137
138         info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
139         if (!info) {
140                 return_ACPI_STATUS(AE_NO_MEMORY);
141         }
142
143         info->pathname =
144             ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
145
146         /* Evaluate the namespace object containing the values for this state */
147
148         status = acpi_ns_evaluate(info);
149         if (ACPI_FAILURE(status)) {
150                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
151                                   "%s while evaluating SleepState [%s]\n",
152                                   acpi_format_exception(status),
153                                   info->pathname));
154
155                 goto cleanup;
156         }
157
158         /* Must have a return object */
159
160         if (!info->return_object) {
161                 ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
162                             info->pathname));
163                 status = AE_NOT_EXIST;
164         }
165
166         /* It must be of type Package */
167
168         else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
169                 ACPI_ERROR((AE_INFO,
170                             "Sleep State return object is not a Package"));
171                 status = AE_AML_OPERAND_TYPE;
172         }
173
174         /*
175          * The package must have at least two elements. NOTE (March 2005): This
176          * goes against the current ACPI spec which defines this object as a
177          * package with one encoded DWORD element. However, existing practice
178          * by BIOS vendors seems to be to have 2 or more elements, at least
179          * one per sleep type (A/B).
180          */
181         else if (info->return_object->package.count < 2) {
182                 ACPI_ERROR((AE_INFO,
183                             "Sleep State return package does not have at least two elements"));
184                 status = AE_AML_NO_OPERAND;
185         }
186
187         /* The first two elements must both be of type Integer */
188
189         else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
190                   != ACPI_TYPE_INTEGER) ||
191                  (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
192                   != ACPI_TYPE_INTEGER)) {
193                 ACPI_ERROR((AE_INFO,
194                             "Sleep State return package elements are not both Integers (%s, %s)",
195                             acpi_ut_get_object_type_name(info->return_object->
196                                                          package.elements[0]),
197                             acpi_ut_get_object_type_name(info->return_object->
198                                                          package.elements[1])));
199                 status = AE_AML_OPERAND_TYPE;
200         } else {
201                 /* Valid _Sx_ package size, type, and value */
202
203                 *sleep_type_a = (u8)
204                     (info->return_object->package.elements[0])->integer.value;
205                 *sleep_type_b = (u8)
206                     (info->return_object->package.elements[1])->integer.value;
207         }
208
209         if (ACPI_FAILURE(status)) {
210                 ACPI_EXCEPTION((AE_INFO, status,
211                                 "While evaluating SleepState [%s], bad Sleep object %p type %s",
212                                 info->pathname, info->return_object,
213                                 acpi_ut_get_object_type_name(info->
214                                                              return_object)));
215         }
216
217         acpi_ut_remove_reference(info->return_object);
218
219       cleanup:
220         ACPI_FREE(info);
221         return_ACPI_STATUS(status);
222 }
223
224 ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
225
226 /*******************************************************************************
227  *
228  * FUNCTION:    acpi_hw_get_register_bit_mask
229  *
230  * PARAMETERS:  register_id         - Index of ACPI Register to access
231  *
232  * RETURN:      The bitmask to be used when accessing the register
233  *
234  * DESCRIPTION: Map register_id into a register bitmask.
235  *
236  ******************************************************************************/
237 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
238 {
239         ACPI_FUNCTION_ENTRY();
240
241         if (register_id > ACPI_BITREG_MAX) {
242                 ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
243                             register_id));
244                 return (NULL);
245         }
246
247         return (&acpi_gbl_bit_register_info[register_id]);
248 }
249
250 /*******************************************************************************
251  *
252  * FUNCTION:    acpi_get_register
253  *
254  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
255  *              return_value    - Value that was read from the register
256  *              Flags           - Lock the hardware or not
257  *
258  * RETURN:      Status and the value read from specified Register. Value
259  *              returned is normalized to bit0 (is shifted all the way right)
260  *
261  * DESCRIPTION: ACPI bit_register read function.
262  *
263  * NOTE: TBD: Flags parameter is obsolete, to be removed
264  *
265  ******************************************************************************/
266
267 acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
268 {
269         u32 register_value = 0;
270         struct acpi_bit_register_info *bit_reg_info;
271         acpi_status status;
272
273         ACPI_FUNCTION_TRACE(acpi_get_register);
274
275         /* Get the info structure corresponding to the requested ACPI Register */
276
277         bit_reg_info = acpi_hw_get_bit_register_info(register_id);
278         if (!bit_reg_info) {
279                 return_ACPI_STATUS(AE_BAD_PARAMETER);
280         }
281
282         /* Read from the register */
283
284         status = acpi_hw_register_read(ACPI_MTX_LOCK,
285                                        bit_reg_info->parent_register,
286                                        &register_value);
287
288         if (ACPI_SUCCESS(status)) {
289
290                 /* Normalize the value that was read */
291
292                 register_value =
293                     ((register_value & bit_reg_info->access_bit_mask)
294                      >> bit_reg_info->bit_position);
295
296                 *return_value = register_value;
297
298                 ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n",
299                                   register_value,
300                                   bit_reg_info->parent_register));
301         }
302
303         return_ACPI_STATUS(status);
304 }
305
306 ACPI_EXPORT_SYMBOL(acpi_get_register)
307
308 /*******************************************************************************
309  *
310  * FUNCTION:    acpi_set_register
311  *
312  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
313  *              Value           - (only used on write) value to write to the
314  *                                Register, NOT pre-normalized to the bit pos
315  *              Flags           - Lock the hardware or not
316  *
317  * RETURN:      Status
318  *
319  * DESCRIPTION: ACPI Bit Register write function.
320  *
321  * NOTE: TBD: Flags parameter is obsolete, to be removed
322  *
323  ******************************************************************************/
324 acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
325 {
326         u32 register_value = 0;
327         struct acpi_bit_register_info *bit_reg_info;
328         acpi_status status;
329         acpi_cpu_flags lock_flags;
330
331         ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id);
332
333         /* Get the info structure corresponding to the requested ACPI Register */
334
335         bit_reg_info = acpi_hw_get_bit_register_info(register_id);
336         if (!bit_reg_info) {
337                 ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X",
338                             register_id));
339                 return_ACPI_STATUS(AE_BAD_PARAMETER);
340         }
341
342         lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
343
344         /* Always do a register read first so we can insert the new bits  */
345
346         status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
347                                        bit_reg_info->parent_register,
348                                        &register_value);
349         if (ACPI_FAILURE(status)) {
350                 goto unlock_and_exit;
351         }
352
353         /*
354          * Decode the Register ID
355          * Register ID = [Register block ID] | [bit ID]
356          *
357          * Check bit ID to fine locate Register offset.
358          * Check Mask to determine Register offset, and then read-write.
359          */
360         switch (bit_reg_info->parent_register) {
361         case ACPI_REGISTER_PM1_STATUS:
362
363                 /*
364                  * Status Registers are different from the rest. Clear by
365                  * writing 1, and writing 0 has no effect. So, the only relevant
366                  * information is the single bit we're interested in, all others should
367                  * be written as 0 so they will be left unchanged.
368                  */
369                 value = ACPI_REGISTER_PREPARE_BITS(value,
370                                                    bit_reg_info->bit_position,
371                                                    bit_reg_info->
372                                                    access_bit_mask);
373                 if (value) {
374                         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
375                                                         ACPI_REGISTER_PM1_STATUS,
376                                                         (u16) value);
377                         register_value = 0;
378                 }
379                 break;
380
381         case ACPI_REGISTER_PM1_ENABLE:
382
383                 ACPI_REGISTER_INSERT_VALUE(register_value,
384                                            bit_reg_info->bit_position,
385                                            bit_reg_info->access_bit_mask,
386                                            value);
387
388                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
389                                                 ACPI_REGISTER_PM1_ENABLE,
390                                                 (u16) register_value);
391                 break;
392
393         case ACPI_REGISTER_PM1_CONTROL:
394
395                 /*
396                  * Write the PM1 Control register.
397                  * Note that at this level, the fact that there are actually TWO
398                  * registers (A and B - and B may not exist) is abstracted.
399                  */
400                 ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n",
401                                   register_value));
402
403                 ACPI_REGISTER_INSERT_VALUE(register_value,
404                                            bit_reg_info->bit_position,
405                                            bit_reg_info->access_bit_mask,
406                                            value);
407
408                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
409                                                 ACPI_REGISTER_PM1_CONTROL,
410                                                 (u16) register_value);
411                 break;
412
413         case ACPI_REGISTER_PM2_CONTROL:
414
415                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
416                                                ACPI_REGISTER_PM2_CONTROL,
417                                                &register_value);
418                 if (ACPI_FAILURE(status)) {
419                         goto unlock_and_exit;
420                 }
421
422                 ACPI_DEBUG_PRINT((ACPI_DB_IO,
423                                   "PM2 control: Read %X from %8.8X%8.8X\n",
424                                   register_value,
425                                   ACPI_FORMAT_UINT64(acpi_gbl_FADT->
426                                                      xpm2_cnt_blk.address)));
427
428                 ACPI_REGISTER_INSERT_VALUE(register_value,
429                                            bit_reg_info->bit_position,
430                                            bit_reg_info->access_bit_mask,
431                                            value);
432
433                 ACPI_DEBUG_PRINT((ACPI_DB_IO,
434                                   "About to write %4.4X to %8.8X%8.8X\n",
435                                   register_value,
436                                   ACPI_FORMAT_UINT64(acpi_gbl_FADT->
437                                                      xpm2_cnt_blk.address)));
438
439                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
440                                                 ACPI_REGISTER_PM2_CONTROL,
441                                                 (u8) (register_value));
442                 break;
443
444         default:
445                 break;
446         }
447
448       unlock_and_exit:
449
450         acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
451
452         /* Normalize the value that was read */
453
454         ACPI_DEBUG_EXEC(register_value =
455                         ((register_value & bit_reg_info->access_bit_mask) >>
456                          bit_reg_info->bit_position));
457
458         ACPI_DEBUG_PRINT((ACPI_DB_IO,
459                           "Set bits: %8.8X actual %8.8X register %X\n", value,
460                           register_value, bit_reg_info->parent_register));
461         return_ACPI_STATUS(status);
462 }
463
464 ACPI_EXPORT_SYMBOL(acpi_set_register)
465
466 /******************************************************************************
467  *
468  * FUNCTION:    acpi_hw_register_read
469  *
470  * PARAMETERS:  use_lock            - Lock hardware? True/False
471  *              register_id         - ACPI Register ID
472  *              return_value        - Where the register value is returned
473  *
474  * RETURN:      Status and the value read.
475  *
476  * DESCRIPTION: Read from the specified ACPI register
477  *
478  ******************************************************************************/
479 acpi_status
480 acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
481 {
482         u32 value1 = 0;
483         u32 value2 = 0;
484         acpi_status status;
485         acpi_cpu_flags lock_flags = 0;
486
487         ACPI_FUNCTION_TRACE(hw_register_read);
488
489         if (ACPI_MTX_LOCK == use_lock) {
490                 lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
491         }
492
493         switch (register_id) {
494         case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
495
496                 status =
497                     acpi_hw_low_level_read(16, &value1,
498                                            &acpi_gbl_FADT->xpm1a_evt_blk);
499                 if (ACPI_FAILURE(status)) {
500                         goto unlock_and_exit;
501                 }
502
503                 /* PM1B is optional */
504
505                 status =
506                     acpi_hw_low_level_read(16, &value2,
507                                            &acpi_gbl_FADT->xpm1b_evt_blk);
508                 value1 |= value2;
509                 break;
510
511         case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
512
513                 status =
514                     acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
515                 if (ACPI_FAILURE(status)) {
516                         goto unlock_and_exit;
517                 }
518
519                 /* PM1B is optional */
520
521                 status =
522                     acpi_hw_low_level_read(16, &value2, &acpi_gbl_xpm1b_enable);
523                 value1 |= value2;
524                 break;
525
526         case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
527
528                 status =
529                     acpi_hw_low_level_read(16, &value1,
530                                            &acpi_gbl_FADT->xpm1a_cnt_blk);
531                 if (ACPI_FAILURE(status)) {
532                         goto unlock_and_exit;
533                 }
534
535                 status =
536                     acpi_hw_low_level_read(16, &value2,
537                                            &acpi_gbl_FADT->xpm1b_cnt_blk);
538                 value1 |= value2;
539                 break;
540
541         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
542
543                 status =
544                     acpi_hw_low_level_read(8, &value1,
545                                            &acpi_gbl_FADT->xpm2_cnt_blk);
546                 break;
547
548         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
549
550                 status =
551                     acpi_hw_low_level_read(32, &value1,
552                                            &acpi_gbl_FADT->xpm_tmr_blk);
553                 break;
554
555         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
556
557                 status = acpi_os_read_port(acpi_gbl_FADT->smi_cmd, &value1, 8);
558                 break;
559
560         default:
561                 ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
562                 status = AE_BAD_PARAMETER;
563                 break;
564         }
565
566       unlock_and_exit:
567         if (ACPI_MTX_LOCK == use_lock) {
568                 acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
569         }
570
571         if (ACPI_SUCCESS(status)) {
572                 *return_value = value1;
573         }
574
575         return_ACPI_STATUS(status);
576 }
577
578 /******************************************************************************
579  *
580  * FUNCTION:    acpi_hw_register_write
581  *
582  * PARAMETERS:  use_lock            - Lock hardware? True/False
583  *              register_id         - ACPI Register ID
584  *              Value               - The value to write
585  *
586  * RETURN:      Status
587  *
588  * DESCRIPTION: Write to the specified ACPI register
589  *
590  * NOTE: In accordance with the ACPI specification, this function automatically
591  * preserves the value of the following bits, meaning that these bits cannot be
592  * changed via this interface:
593  *
594  * PM1_CONTROL[0] = SCI_EN
595  * PM1_CONTROL[9]
596  * PM1_STATUS[11]
597  *
598  * ACPI References:
599  * 1) Hardware Ignored Bits: When software writes to a register with ignored
600  *      bit fields, it preserves the ignored bit fields
601  * 2) SCI_EN: OSPM always preserves this bit position
602  *
603  ******************************************************************************/
604
605 acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
606 {
607         acpi_status status;
608         acpi_cpu_flags lock_flags = 0;
609         u32 read_value;
610
611         ACPI_FUNCTION_TRACE(hw_register_write);
612
613         if (ACPI_MTX_LOCK == use_lock) {
614                 lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
615         }
616
617         switch (register_id) {
618         case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
619
620                 /* Perform a read first to preserve certain bits (per ACPI spec) */
621
622                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
623                                                ACPI_REGISTER_PM1_STATUS,
624                                                &read_value);
625                 if (ACPI_FAILURE(status)) {
626                         goto unlock_and_exit;
627                 }
628
629                 /* Insert the bits to be preserved */
630
631                 ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
632                                  read_value);
633
634                 /* Now we can write the data */
635
636                 status =
637                     acpi_hw_low_level_write(16, value,
638                                             &acpi_gbl_FADT->xpm1a_evt_blk);
639                 if (ACPI_FAILURE(status)) {
640                         goto unlock_and_exit;
641                 }
642
643                 /* PM1B is optional */
644
645                 status =
646                     acpi_hw_low_level_write(16, value,
647                                             &acpi_gbl_FADT->xpm1b_evt_blk);
648                 break;
649
650         case ACPI_REGISTER_PM1_ENABLE:  /* 16-bit access */
651
652                 status =
653                     acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
654                 if (ACPI_FAILURE(status)) {
655                         goto unlock_and_exit;
656                 }
657
658                 /* PM1B is optional */
659
660                 status =
661                     acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1b_enable);
662                 break;
663
664         case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
665
666                 /*
667                  * Perform a read first to preserve certain bits (per ACPI spec)
668                  */
669                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
670                                                ACPI_REGISTER_PM1_CONTROL,
671                                                &read_value);
672                 if (ACPI_FAILURE(status)) {
673                         goto unlock_and_exit;
674                 }
675
676                 /* Insert the bits to be preserved */
677
678                 ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
679                                  read_value);
680
681                 /* Now we can write the data */
682
683                 status =
684                     acpi_hw_low_level_write(16, value,
685                                             &acpi_gbl_FADT->xpm1a_cnt_blk);
686                 if (ACPI_FAILURE(status)) {
687                         goto unlock_and_exit;
688                 }
689
690                 status =
691                     acpi_hw_low_level_write(16, value,
692                                             &acpi_gbl_FADT->xpm1b_cnt_blk);
693                 break;
694
695         case ACPI_REGISTER_PM1A_CONTROL:        /* 16-bit access */
696
697                 status =
698                     acpi_hw_low_level_write(16, value,
699                                             &acpi_gbl_FADT->xpm1a_cnt_blk);
700                 break;
701
702         case ACPI_REGISTER_PM1B_CONTROL:        /* 16-bit access */
703
704                 status =
705                     acpi_hw_low_level_write(16, value,
706                                             &acpi_gbl_FADT->xpm1b_cnt_blk);
707                 break;
708
709         case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
710
711                 status =
712                     acpi_hw_low_level_write(8, value,
713                                             &acpi_gbl_FADT->xpm2_cnt_blk);
714                 break;
715
716         case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
717
718                 status =
719                     acpi_hw_low_level_write(32, value,
720                                             &acpi_gbl_FADT->xpm_tmr_blk);
721                 break;
722
723         case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
724
725                 /* SMI_CMD is currently always in IO space */
726
727                 status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, value, 8);
728                 break;
729
730         default:
731                 status = AE_BAD_PARAMETER;
732                 break;
733         }
734
735       unlock_and_exit:
736         if (ACPI_MTX_LOCK == use_lock) {
737                 acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
738         }
739
740         return_ACPI_STATUS(status);
741 }
742
743 /******************************************************************************
744  *
745  * FUNCTION:    acpi_hw_low_level_read
746  *
747  * PARAMETERS:  Width               - 8, 16, or 32
748  *              Value               - Where the value is returned
749  *              Reg                 - GAS register structure
750  *
751  * RETURN:      Status
752  *
753  * DESCRIPTION: Read from either memory or IO space.
754  *
755  ******************************************************************************/
756
757 acpi_status
758 acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
759 {
760         u64 address;
761         acpi_status status;
762
763         ACPI_FUNCTION_NAME(hw_low_level_read);
764
765         /*
766          * Must have a valid pointer to a GAS structure, and
767          * a non-zero address within. However, don't return an error
768          * because the PM1A/B code must not fail if B isn't present.
769          */
770         if (!reg) {
771                 return (AE_OK);
772         }
773
774         /* Get a local copy of the address. Handles possible alignment issues */
775
776         ACPI_MOVE_64_TO_64(&address, &reg->address);
777         if (!address) {
778                 return (AE_OK);
779         }
780         *value = 0;
781
782         /*
783          * Two address spaces supported: Memory or IO.
784          * PCI_Config is not supported here because the GAS struct is insufficient
785          */
786         switch (reg->address_space_id) {
787         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
788
789                 status = acpi_os_read_memory((acpi_physical_address) address,
790                                              value, width);
791                 break;
792
793         case ACPI_ADR_SPACE_SYSTEM_IO:
794
795                 status = acpi_os_read_port((acpi_io_address) address,
796                                            value, width);
797                 break;
798
799         default:
800                 ACPI_ERROR((AE_INFO,
801                             "Unsupported address space: %X",
802                             reg->address_space_id));
803                 return (AE_BAD_PARAMETER);
804         }
805
806         ACPI_DEBUG_PRINT((ACPI_DB_IO,
807                           "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
808                           *value, width,
809                           ACPI_FORMAT_UINT64(address),
810                           acpi_ut_get_region_name(reg->address_space_id)));
811
812         return (status);
813 }
814
815 /******************************************************************************
816  *
817  * FUNCTION:    acpi_hw_low_level_write
818  *
819  * PARAMETERS:  Width               - 8, 16, or 32
820  *              Value               - To be written
821  *              Reg                 - GAS register structure
822  *
823  * RETURN:      Status
824  *
825  * DESCRIPTION: Write to either memory or IO space.
826  *
827  ******************************************************************************/
828
829 acpi_status
830 acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
831 {
832         u64 address;
833         acpi_status status;
834
835         ACPI_FUNCTION_NAME(hw_low_level_write);
836
837         /*
838          * Must have a valid pointer to a GAS structure, and
839          * a non-zero address within. However, don't return an error
840          * because the PM1A/B code must not fail if B isn't present.
841          */
842         if (!reg) {
843                 return (AE_OK);
844         }
845
846         /* Get a local copy of the address. Handles possible alignment issues */
847
848         ACPI_MOVE_64_TO_64(&address, &reg->address);
849         if (!address) {
850                 return (AE_OK);
851         }
852
853         /*
854          * Two address spaces supported: Memory or IO.
855          * PCI_Config is not supported here because the GAS struct is insufficient
856          */
857         switch (reg->address_space_id) {
858         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
859
860                 status = acpi_os_write_memory((acpi_physical_address) address,
861                                               value, width);
862                 break;
863
864         case ACPI_ADR_SPACE_SYSTEM_IO:
865
866                 status = acpi_os_write_port((acpi_io_address) address,
867                                             value, width);
868                 break;
869
870         default:
871                 ACPI_ERROR((AE_INFO,
872                             "Unsupported address space: %X",
873                             reg->address_space_id));
874                 return (AE_BAD_PARAMETER);
875         }
876
877         ACPI_DEBUG_PRINT((ACPI_DB_IO,
878                           "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
879                           value, width,
880                           ACPI_FORMAT_UINT64(address),
881                           acpi_ut_get_region_name(reg->address_space_id)));
882
883         return (status);
884 }