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                  ValueLo;
135    UINT32                  ValueHi;
136    UINT32                  Width;
137    UINT64                  Address;
138    ACPI_STATUS             Status;
139
140
141    ACPI_FUNCTION_NAME (AcpiRead);
142
143
144    if (!ReturnValue)
145    {
146        return (AE_BAD_PARAMETER);
147    }
148
149    /* Validate contents of the GAS register. Allow 64-bit transfers */
150
151    Status = AcpiHwValidateRegister (Reg, 64, &Address);
152    if (ACPI_FAILURE (Status))
153    {
154        return (Status);
155    }
156
157    /*
158     * Two address spaces supported: Memory or I/O. PCI_Config is
159     * not supported here because the GAS structure is insufficient
160     */
161    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
162    {
163        Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
164                    Address, ReturnValue, Reg->BitWidth);
165        if (ACPI_FAILURE (Status))
166        {
167            return (Status);
168        }
169    }
170    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
171    {
172        ValueLo = 0;
173        ValueHi = 0;
174
175        Width = Reg->BitWidth;
176        if (Width == 64)
177        {
178            Width = 32; /* Break into two 32-bit transfers */
179        }
180
181        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
182                    Address, &ValueLo, Width);
183        if (ACPI_FAILURE (Status))
184        {
185            return (Status);
186        }
187
188        if (Reg->BitWidth == 64)
189        {
190            /* Read the top 32 bits */
191
192            Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
193                        (Address + 4), &ValueHi, 32);
194            if (ACPI_FAILURE (Status))
195            {
196                return (Status);
197            }
198        }
199
200        /* Set the return value only if status is AE_OK */
201
202        *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32));
203    }
204
205    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
206        "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
207        ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
208        ACPI_FORMAT_UINT64 (Address),
209        AcpiUtGetRegionName (Reg->SpaceId)));
210
211    return (AE_OK);
212}
213
214ACPI_EXPORT_SYMBOL (AcpiRead)
215
216
217/******************************************************************************
218 *
219 * FUNCTION:    AcpiWrite
220 *
221 * PARAMETERS:  Value               - Value to be written
222 *              Reg                 - GAS register structure
223 *
224 * RETURN:      Status
225 *
226 * DESCRIPTION: Write to either memory or IO space.
227 *
228 ******************************************************************************/
229
230ACPI_STATUS
231AcpiWrite (
232    UINT64                  Value,
233    ACPI_GENERIC_ADDRESS    *Reg)
234{
235    UINT32                  Width;
236    UINT64                  Address;
237    ACPI_STATUS             Status;
238
239
240    ACPI_FUNCTION_NAME (AcpiWrite);
241
242
243    /* Validate contents of the GAS register. Allow 64-bit transfers */
244
245    Status = AcpiHwValidateRegister (Reg, 64, &Address);
246    if (ACPI_FAILURE (Status))
247    {
248        return (Status);
249    }
250
251    /*
252     * Two address spaces supported: Memory or IO. PCI_Config is
253     * not supported here because the GAS structure is insufficient
254     */
255    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
256    {
257        Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
258                    Address, Value, Reg->BitWidth);
259        if (ACPI_FAILURE (Status))
260        {
261            return (Status);
262        }
263    }
264    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
265    {
266        Width = Reg->BitWidth;
267        if (Width == 64)
268        {
269            Width = 32; /* Break into two 32-bit transfers */
270        }
271
272        Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
273                    Address, ACPI_LODWORD (Value), Width);
274        if (ACPI_FAILURE (Status))
275        {
276            return (Status);
277        }
278
279        if (Reg->BitWidth == 64)
280        {
281            Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
282                        (Address + 4), ACPI_HIDWORD (Value), 32);
283            if (ACPI_FAILURE (Status))
284            {
285                return (Status);
286            }
287        }
288    }
289
290    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
291        "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
292        ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
293        ACPI_FORMAT_UINT64 (Address),
294        AcpiUtGetRegionName (Reg->SpaceId)));
295
296    return (Status);
297}
298
299ACPI_EXPORT_SYMBOL (AcpiWrite)
300
301
302#if (!ACPI_REDUCED_HARDWARE)
303/*******************************************************************************
304 *
305 * FUNCTION:    AcpiReadBitRegister
306 *
307 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
308 *              ReturnValue     - Value that was read from the register,
309 *                                normalized to bit position zero.
310 *
311 * RETURN:      Status and the value read from the specified Register. Value
312 *              returned is normalized to bit0 (is shifted all the way right)
313 *
314 * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
315 *
316 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
317 *              PM2 Control.
318 *
319 * Note: The hardware lock is not required when reading the ACPI bit registers
320 *       since almost all of them are single bit and it does not matter that
321 *       the parent hardware register can be split across two physical
322 *       registers. The only multi-bit field is SLP_TYP in the PM1 control
323 *       register, but this field does not cross an 8-bit boundary (nor does
324 *       it make much sense to actually read this field.)
325 *
326 ******************************************************************************/
327
328ACPI_STATUS
329AcpiReadBitRegister (
330    UINT32                  RegisterId,
331    UINT32                  *ReturnValue)
332{
333    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
334    UINT32                  RegisterValue;
335    UINT32                  Value;
336    ACPI_STATUS             Status;
337
338
339    ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
340
341
342    /* Get the info structure corresponding to the requested ACPI Register */
343
344    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
345    if (!BitRegInfo)
346    {
347        return_ACPI_STATUS (AE_BAD_PARAMETER);
348    }
349
350    /* Read the entire parent register */
351
352    Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
353                &RegisterValue);
354    if (ACPI_FAILURE (Status))
355    {
356        return_ACPI_STATUS (Status);
357    }
358
359    /* Normalize the value that was read, mask off other bits */
360
361    Value = ((RegisterValue & BitRegInfo->AccessBitMask)
362                >> BitRegInfo->BitPosition);
363
364    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
365        "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
366        RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
367
368    *ReturnValue = Value;
369    return_ACPI_STATUS (AE_OK);
370}
371
372ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
373
374
375/*******************************************************************************
376 *
377 * FUNCTION:    AcpiWriteBitRegister
378 *
379 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
380 *              Value           - Value to write to the register, in bit
381 *                                position zero. The bit is automatically
382 *                                shifted to the correct position.
383 *
384 * RETURN:      Status
385 *
386 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
387 *              since most operations require a read/modify/write sequence.
388 *
389 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
390 *              PM2 Control.
391 *
392 * Note that at this level, the fact that there may be actually two
393 * hardware registers (A and B - and B may not exist) is abstracted.
394 *
395 ******************************************************************************/
396
397ACPI_STATUS
398AcpiWriteBitRegister (
399    UINT32                  RegisterId,
400    UINT32                  Value)
401{
402    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
403    ACPI_CPU_FLAGS          LockFlags;
404    UINT32                  RegisterValue;
405    ACPI_STATUS             Status = AE_OK;
406
407
408    ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
409
410
411    /* Get the info structure corresponding to the requested ACPI Register */
412
413    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
414    if (!BitRegInfo)
415    {
416        return_ACPI_STATUS (AE_BAD_PARAMETER);
417    }
418
419    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
420
421    /*
422     * At this point, we know that the parent register is one of the
423     * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
424     */
425    if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
426    {
427        /*
428         * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
429         *
430         * Perform a register read to preserve the bits that we are not
431         * interested in
432         */
433        Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
434                    &RegisterValue);
435        if (ACPI_FAILURE (Status))
436        {
437            goto UnlockAndExit;
438        }
439
440        /*
441         * Insert the input bit into the value that was just read
442         * and write the register
443         */
444        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
445            BitRegInfo->AccessBitMask, Value);
446
447        Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
448                    RegisterValue);
449    }
450    else
451    {
452        /*
453         * 2) Case for PM1 Status
454         *
455         * The Status register is different from the rest. Clear an event
456         * by writing 1, writing 0 has no effect. So, the only relevant
457         * information is the single bit we're interested in, all others
458         * should be written as 0 so they will be left unchanged.
459         */
460        RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
461            BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
462
463        /* No need to write the register if value is all zeros */
464
465        if (RegisterValue)
466        {
467            Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
468                        RegisterValue);
469        }
470    }
471
472    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
473        "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
474        RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
475
476
477UnlockAndExit:
478
479    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
480    return_ACPI_STATUS (Status);
481}
482
483ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
484
485#endif /* !ACPI_REDUCED_HARDWARE */
486
487
488/*******************************************************************************
489 *
490 * FUNCTION:    AcpiGetSleepTypeData
491 *
492 * PARAMETERS:  SleepState          - Numeric sleep state
493 *              *SleepTypeA         - Where SLP_TYPa is returned
494 *              *SleepTypeB         - Where SLP_TYPb is returned
495 *
496 * RETURN:      Status
497 *
498 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
499 *              sleep state via the appropriate \_Sx object.
500 *
501 *  The sleep state package returned from the corresponding \_Sx_ object
502 *  must contain at least one integer.
503 *
504 *  March 2005:
505 *  Added support for a package that contains two integers. This
506 *  goes against the ACPI specification which defines this object as a
507 *  package with one encoded DWORD integer. However, existing practice
508 *  by many BIOS vendors is to return a package with 2 or more integer
509 *  elements, at least one per sleep type (A/B).
510 *
511 *  January 2013:
512 *  Therefore, we must be prepared to accept a package with either a
513 *  single integer or multiple integers.
514 *
515 *  The single integer DWORD format is as follows:
516 *      BYTE 0 - Value for the PM1A SLP_TYP register
517 *      BYTE 1 - Value for the PM1B SLP_TYP register
518 *      BYTE 2-3 - Reserved
519 *
520 *  The dual integer format is as follows:
521 *      Integer 0 - Value for the PM1A SLP_TYP register
522 *      Integer 1 - Value for the PM1A SLP_TYP register
523 *
524 ******************************************************************************/
525
526ACPI_STATUS
527AcpiGetSleepTypeData (
528    UINT8                   SleepState,
529    UINT8                   *SleepTypeA,
530    UINT8                   *SleepTypeB)
531{
532    ACPI_STATUS             Status;
533    ACPI_EVALUATE_INFO      *Info;
534    ACPI_OPERAND_OBJECT     **Elements;
535
536
537    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
538
539
540    /* Validate parameters */
541
542    if ((SleepState > ACPI_S_STATES_MAX) ||
543        !SleepTypeA || !SleepTypeB)
544    {
545        return_ACPI_STATUS (AE_BAD_PARAMETER);
546    }
547
548    /* Allocate the evaluation information block */
549
550    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
551    if (!Info)
552    {
553        return_ACPI_STATUS (AE_NO_MEMORY);
554    }
555
556    /*
557     * Evaluate the \_Sx namespace object containing the register values
558     * for this state
559     */
560    Info->RelativePathname = ACPI_CAST_PTR (
561        char, AcpiGbl_SleepStateNames[SleepState]);
562    Status = AcpiNsEvaluate (Info);
563    if (ACPI_FAILURE (Status))
564    {
565        goto Cleanup;
566    }
567
568    /* Must have a return object */
569
570    if (!Info->ReturnObject)
571    {
572        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
573            Info->RelativePathname));
574        Status = AE_AML_NO_RETURN_VALUE;
575        goto Cleanup;
576    }
577
578    /* Return object must be of type Package */
579
580    if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
581    {
582        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
583        Status = AE_AML_OPERAND_TYPE;
584        goto Cleanup1;
585    }
586
587    /*
588     * Any warnings about the package length or the object types have
589     * already been issued by the predefined name module -- there is no
590     * need to repeat them here.
591     */
592    Elements = Info->ReturnObject->Package.Elements;
593    switch (Info->ReturnObject->Package.Count)
594    {
595    case 0:
596
597        Status = AE_AML_PACKAGE_LIMIT;
598        break;
599
600    case 1:
601
602        if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
603        {
604            Status = AE_AML_OPERAND_TYPE;
605            break;
606        }
607
608        /* A valid _Sx_ package with one integer */
609
610        *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
611        *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
612        break;
613
614    case 2:
615    default:
616
617        if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
618            (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
619        {
620            Status = AE_AML_OPERAND_TYPE;
621            break;
622        }
623
624        /* A valid _Sx_ package with two integers */
625
626        *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
627        *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
628        break;
629    }
630
631Cleanup1:
632    AcpiUtRemoveReference (Info->ReturnObject);
633
634Cleanup:
635    if (ACPI_FAILURE (Status))
636    {
637        ACPI_EXCEPTION ((AE_INFO, Status,
638            "While evaluating Sleep State [%s]", Info->RelativePathname));
639    }
640
641    ACPI_FREE (Info);
642    return_ACPI_STATUS (Status);
643}
644
645ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
646