hwxface.c revision 250838
1/******************************************************************************
2 *
3 * Module Name: hwxface - Public ACPICA hardware interfaces
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acnamesp.h>
47
48#define _COMPONENT          ACPI_HARDWARE
49        ACPI_MODULE_NAME    ("hwxface")
50
51
52/******************************************************************************
53 *
54 * FUNCTION:    AcpiReset
55 *
56 * PARAMETERS:  None
57 *
58 * RETURN:      Status
59 *
60 * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
61 *              support reset register in PCI config space, this must be
62 *              handled separately.
63 *
64 ******************************************************************************/
65
66ACPI_STATUS
67AcpiReset (
68    void)
69{
70    ACPI_GENERIC_ADDRESS    *ResetReg;
71    ACPI_STATUS             Status;
72
73
74    ACPI_FUNCTION_TRACE (AcpiReset);
75
76
77    ResetReg = &AcpiGbl_FADT.ResetRegister;
78
79    /* Check if the reset register is supported */
80
81    if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
82        !ResetReg->Address)
83    {
84        return_ACPI_STATUS (AE_NOT_EXIST);
85    }
86
87    if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
88    {
89        /*
90         * For I/O space, write directly to the OSL. This bypasses the port
91         * validation mechanism, which may block a valid write to the reset
92         * register.
93         */
94        Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
95                    AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
96    }
97    else
98    {
99        /* Write the reset value to the reset register */
100
101        Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
102    }
103
104    return_ACPI_STATUS (Status);
105}
106
107ACPI_EXPORT_SYMBOL (AcpiReset)
108
109
110/******************************************************************************
111 *
112 * FUNCTION:    AcpiRead
113 *
114 * PARAMETERS:  Value               - Where the value is returned
115 *              Reg                 - GAS register structure
116 *
117 * RETURN:      Status
118 *
119 * DESCRIPTION: Read from either memory or IO space.
120 *
121 * LIMITATIONS: <These limitations also apply to AcpiWrite>
122 *      BitWidth must be exactly 8, 16, 32, or 64.
123 *      SpaceID must be SystemMemory or SystemIO.
124 *      BitOffset and AccessWidth are currently ignored, as there has
125 *          not been a need to implement these.
126 *
127 ******************************************************************************/
128
129ACPI_STATUS
130AcpiRead (
131    UINT64                  *ReturnValue,
132    ACPI_GENERIC_ADDRESS    *Reg)
133{
134    UINT32                  Value;
135    UINT32                  Width;
136    UINT64                  Address;
137    ACPI_STATUS             Status;
138
139
140    ACPI_FUNCTION_NAME (AcpiRead);
141
142
143    if (!ReturnValue)
144    {
145        return (AE_BAD_PARAMETER);
146    }
147
148    /* Validate contents of the GAS register. Allow 64-bit transfers */
149
150    Status = AcpiHwValidateRegister (Reg, 64, &Address);
151    if (ACPI_FAILURE (Status))
152    {
153        return (Status);
154    }
155
156    /* Initialize entire 64-bit return value to zero */
157
158    *ReturnValue = 0;
159    Value = 0;
160
161    /*
162     * Two address spaces supported: Memory or IO. PCI_Config is
163     * not supported here because the GAS structure is insufficient
164     */
165    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
166    {
167        Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
168                    Address, ReturnValue, Reg->BitWidth);
169        if (ACPI_FAILURE (Status))
170        {
171            return (Status);
172        }
173    }
174    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
175    {
176        Width = Reg->BitWidth;
177        if (Width == 64)
178        {
179            Width = 32; /* Break into two 32-bit transfers */
180        }
181
182        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
183                    Address, &Value, Width);
184        if (ACPI_FAILURE (Status))
185        {
186            return (Status);
187        }
188        *ReturnValue = Value;
189
190        if (Reg->BitWidth == 64)
191        {
192            /* Read the top 32 bits */
193
194            Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
195                        (Address + 4), &Value, 32);
196            if (ACPI_FAILURE (Status))
197            {
198                return (Status);
199            }
200            *ReturnValue |= ((UINT64) Value << 32);
201        }
202    }
203
204    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
205        "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
206        ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
207        ACPI_FORMAT_UINT64 (Address),
208        AcpiUtGetRegionName (Reg->SpaceId)));
209
210    return (Status);
211}
212
213ACPI_EXPORT_SYMBOL (AcpiRead)
214
215
216/******************************************************************************
217 *
218 * FUNCTION:    AcpiWrite
219 *
220 * PARAMETERS:  Value               - Value to be written
221 *              Reg                 - GAS register structure
222 *
223 * RETURN:      Status
224 *
225 * DESCRIPTION: Write to either memory or IO space.
226 *
227 ******************************************************************************/
228
229ACPI_STATUS
230AcpiWrite (
231    UINT64                  Value,
232    ACPI_GENERIC_ADDRESS    *Reg)
233{
234    UINT32                  Width;
235    UINT64                  Address;
236    ACPI_STATUS             Status;
237
238
239    ACPI_FUNCTION_NAME (AcpiWrite);
240
241
242    /* Validate contents of the GAS register. Allow 64-bit transfers */
243
244    Status = AcpiHwValidateRegister (Reg, 64, &Address);
245    if (ACPI_FAILURE (Status))
246    {
247        return (Status);
248    }
249
250    /*
251     * Two address spaces supported: Memory or IO. PCI_Config is
252     * not supported here because the GAS structure is insufficient
253     */
254    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
255    {
256        Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
257                    Address, Value, Reg->BitWidth);
258        if (ACPI_FAILURE (Status))
259        {
260            return (Status);
261        }
262    }
263    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
264    {
265        Width = Reg->BitWidth;
266        if (Width == 64)
267        {
268            Width = 32; /* Break into two 32-bit transfers */
269        }
270
271        Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
272                    Address, ACPI_LODWORD (Value), Width);
273        if (ACPI_FAILURE (Status))
274        {
275            return (Status);
276        }
277
278        if (Reg->BitWidth == 64)
279        {
280            Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
281                        (Address + 4), ACPI_HIDWORD (Value), 32);
282            if (ACPI_FAILURE (Status))
283            {
284                return (Status);
285            }
286        }
287    }
288
289    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
290        "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
291        ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
292        ACPI_FORMAT_UINT64 (Address),
293        AcpiUtGetRegionName (Reg->SpaceId)));
294
295    return (Status);
296}
297
298ACPI_EXPORT_SYMBOL (AcpiWrite)
299
300
301#if (!ACPI_REDUCED_HARDWARE)
302/*******************************************************************************
303 *
304 * FUNCTION:    AcpiReadBitRegister
305 *
306 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
307 *              ReturnValue     - Value that was read from the register,
308 *                                normalized to bit position zero.
309 *
310 * RETURN:      Status and the value read from the specified Register. Value
311 *              returned is normalized to bit0 (is shifted all the way right)
312 *
313 * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
314 *
315 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
316 *              PM2 Control.
317 *
318 * Note: The hardware lock is not required when reading the ACPI bit registers
319 *       since almost all of them are single bit and it does not matter that
320 *       the parent hardware register can be split across two physical
321 *       registers. The only multi-bit field is SLP_TYP in the PM1 control
322 *       register, but this field does not cross an 8-bit boundary (nor does
323 *       it make much sense to actually read this field.)
324 *
325 ******************************************************************************/
326
327ACPI_STATUS
328AcpiReadBitRegister (
329    UINT32                  RegisterId,
330    UINT32                  *ReturnValue)
331{
332    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
333    UINT32                  RegisterValue;
334    UINT32                  Value;
335    ACPI_STATUS             Status;
336
337
338    ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
339
340
341    /* Get the info structure corresponding to the requested ACPI Register */
342
343    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
344    if (!BitRegInfo)
345    {
346        return_ACPI_STATUS (AE_BAD_PARAMETER);
347    }
348
349    /* Read the entire parent register */
350
351    Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
352                &RegisterValue);
353    if (ACPI_FAILURE (Status))
354    {
355        return_ACPI_STATUS (Status);
356    }
357
358    /* Normalize the value that was read, mask off other bits */
359
360    Value = ((RegisterValue & BitRegInfo->AccessBitMask)
361                >> BitRegInfo->BitPosition);
362
363    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
364        "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
365        RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
366
367    *ReturnValue = Value;
368    return_ACPI_STATUS (AE_OK);
369}
370
371ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
372
373
374/*******************************************************************************
375 *
376 * FUNCTION:    AcpiWriteBitRegister
377 *
378 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
379 *              Value           - Value to write to the register, in bit
380 *                                position zero. The bit is automatically
381 *                                shifted to the correct position.
382 *
383 * RETURN:      Status
384 *
385 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
386 *              since most operations require a read/modify/write sequence.
387 *
388 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
389 *              PM2 Control.
390 *
391 * Note that at this level, the fact that there may be actually two
392 * hardware registers (A and B - and B may not exist) is abstracted.
393 *
394 ******************************************************************************/
395
396ACPI_STATUS
397AcpiWriteBitRegister (
398    UINT32                  RegisterId,
399    UINT32                  Value)
400{
401    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
402    ACPI_CPU_FLAGS          LockFlags;
403    UINT32                  RegisterValue;
404    ACPI_STATUS             Status = AE_OK;
405
406
407    ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
408
409
410    /* Get the info structure corresponding to the requested ACPI Register */
411
412    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
413    if (!BitRegInfo)
414    {
415        return_ACPI_STATUS (AE_BAD_PARAMETER);
416    }
417
418    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
419
420    /*
421     * At this point, we know that the parent register is one of the
422     * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
423     */
424    if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
425    {
426        /*
427         * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
428         *
429         * Perform a register read to preserve the bits that we are not
430         * interested in
431         */
432        Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
433                    &RegisterValue);
434        if (ACPI_FAILURE (Status))
435        {
436            goto UnlockAndExit;
437        }
438
439        /*
440         * Insert the input bit into the value that was just read
441         * and write the register
442         */
443        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
444            BitRegInfo->AccessBitMask, Value);
445
446        Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
447                    RegisterValue);
448    }
449    else
450    {
451        /*
452         * 2) Case for PM1 Status
453         *
454         * The Status register is different from the rest. Clear an event
455         * by writing 1, writing 0 has no effect. So, the only relevant
456         * information is the single bit we're interested in, all others
457         * should be written as 0 so they will be left unchanged.
458         */
459        RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
460            BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
461
462        /* No need to write the register if value is all zeros */
463
464        if (RegisterValue)
465        {
466            Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
467                        RegisterValue);
468        }
469    }
470
471    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
472        "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
473        RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
474
475
476UnlockAndExit:
477
478    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
479    return_ACPI_STATUS (Status);
480}
481
482ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
483
484#endif /* !ACPI_REDUCED_HARDWARE */
485
486
487/*******************************************************************************
488 *
489 * FUNCTION:    AcpiGetSleepTypeData
490 *
491 * PARAMETERS:  SleepState          - Numeric sleep state
492 *              *SleepTypeA         - Where SLP_TYPa is returned
493 *              *SleepTypeB         - Where SLP_TYPb is returned
494 *
495 * RETURN:      Status
496 *
497 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
498 *              sleep state via the appropriate \_Sx object.
499 *
500 *  The sleep state package returned from the corresponding \_Sx_ object
501 *  must contain at least one integer.
502 *
503 *  March 2005:
504 *  Added support for a package that contains two integers. This
505 *  goes against the ACPI specification which defines this object as a
506 *  package with one encoded DWORD integer. However, existing practice
507 *  by many BIOS vendors is to return a package with 2 or more integer
508 *  elements, at least one per sleep type (A/B).
509 *
510 *  January 2013:
511 *  Therefore, we must be prepared to accept a package with either a
512 *  single integer or multiple integers.
513 *
514 *  The single integer DWORD format is as follows:
515 *      BYTE 0 - Value for the PM1A SLP_TYP register
516 *      BYTE 1 - Value for the PM1B SLP_TYP register
517 *      BYTE 2-3 - Reserved
518 *
519 *  The dual integer format is as follows:
520 *      Integer 0 - Value for the PM1A SLP_TYP register
521 *      Integer 1 - Value for the PM1A SLP_TYP register
522 *
523 ******************************************************************************/
524
525ACPI_STATUS
526AcpiGetSleepTypeData (
527    UINT8                   SleepState,
528    UINT8                   *SleepTypeA,
529    UINT8                   *SleepTypeB)
530{
531    ACPI_STATUS             Status;
532    ACPI_EVALUATE_INFO      *Info;
533    ACPI_OPERAND_OBJECT     **Elements;
534
535
536    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
537
538
539    /* Validate parameters */
540
541    if ((SleepState > ACPI_S_STATES_MAX) ||
542        !SleepTypeA || !SleepTypeB)
543    {
544        return_ACPI_STATUS (AE_BAD_PARAMETER);
545    }
546
547    /* Allocate the evaluation information block */
548
549    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
550    if (!Info)
551    {
552        return_ACPI_STATUS (AE_NO_MEMORY);
553    }
554
555    /*
556     * Evaluate the \_Sx namespace object containing the register values
557     * for this state
558     */
559    Info->RelativePathname = ACPI_CAST_PTR (
560        char, AcpiGbl_SleepStateNames[SleepState]);
561    Status = AcpiNsEvaluate (Info);
562    if (ACPI_FAILURE (Status))
563    {
564        goto Cleanup;
565    }
566
567    /* Must have a return object */
568
569    if (!Info->ReturnObject)
570    {
571        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
572            Info->RelativePathname));
573        Status = AE_AML_NO_RETURN_VALUE;
574        goto Cleanup;
575    }
576
577    /* Return object must be of type Package */
578
579    if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
580    {
581        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
582        Status = AE_AML_OPERAND_TYPE;
583        goto Cleanup1;
584    }
585
586    /*
587     * Any warnings about the package length or the object types have
588     * already been issued by the predefined name module -- there is no
589     * need to repeat them here.
590     */
591    Elements = Info->ReturnObject->Package.Elements;
592    switch (Info->ReturnObject->Package.Count)
593    {
594    case 0:
595
596        Status = AE_AML_PACKAGE_LIMIT;
597        break;
598
599    case 1:
600
601        if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
602        {
603            Status = AE_AML_OPERAND_TYPE;
604            break;
605        }
606
607        /* A valid _Sx_ package with one integer */
608
609        *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
610        *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
611        break;
612
613    case 2:
614    default:
615
616        if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
617            (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
618        {
619            Status = AE_AML_OPERAND_TYPE;
620            break;
621        }
622
623        /* A valid _Sx_ package with two integers */
624
625        *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
626        *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
627        break;
628    }
629
630Cleanup1:
631    AcpiUtRemoveReference (Info->ReturnObject);
632
633Cleanup:
634    if (ACPI_FAILURE (Status))
635    {
636        ACPI_EXCEPTION ((AE_INFO, Status,
637            "While evaluating Sleep State [%s]", Info->RelativePathname));
638    }
639
640    ACPI_FREE (Info);
641    return_ACPI_STATUS (Status);
642}
643
644ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
645