2018-03-15 02:13:07 +03:00
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2008-12-30 06:04:48 +03:00
/******************************************************************************
*
* Module Name : hwxface - Public ACPICA hardware interfaces
*
2020-01-10 22:31:49 +03:00
* Copyright ( C ) 2000 - 2020 , Intel Corp .
2008-12-30 06:04:48 +03:00
*
2018-03-15 02:13:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-30 06:04:48 +03:00
2013-10-29 05:29:51 +04:00
# define EXPORT_ACPI_INTERFACES
2008-12-30 06:04:48 +03:00
# include <acpi/acpi.h>
2009-01-09 08:30:03 +03:00
# include "accommon.h"
# include "acnamesp.h"
2008-12-30 06:04:48 +03:00
# define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME ( " hwxface " )
2008-12-30 06:11:57 +03:00
/******************************************************************************
*
* FUNCTION : acpi_reset
*
* PARAMETERS : None
*
* RETURN : Status
*
* DESCRIPTION : Set reset register in memory or IO space . Note : Does not
* support reset register in PCI config space , this must be
* handled separately .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status acpi_reset ( void )
{
struct acpi_generic_address * reset_reg ;
acpi_status status ;
ACPI_FUNCTION_TRACE ( acpi_reset ) ;
reset_reg = & acpi_gbl_FADT . reset_register ;
/* Check if the reset register is supported */
2012-04-20 22:19:35 +04:00
if ( ! ( acpi_gbl_FADT . flags & ACPI_FADT_RESET_REGISTER ) | |
! reset_reg - > address ) {
2008-12-30 06:11:57 +03:00
return_ACPI_STATUS ( AE_NOT_EXIST ) ;
}
2009-08-13 09:42:19 +04:00
if ( reset_reg - > space_id = = ACPI_ADR_SPACE_SYSTEM_IO ) {
/*
2012-12-19 09:36:49 +04:00
* For I / O space , write directly to the OSL . This bypasses the port
* validation mechanism , which may block a valid write to the reset
* register .
2013-10-29 05:29:45 +04:00
*
* NOTE :
* The ACPI spec requires the reset register width to be 8 , so we
* hardcode it here and ignore the FADT value . This maintains
* compatibility with other ACPI implementations that have allowed
* BIOS code with bad register width values to go unnoticed .
2009-08-13 09:42:19 +04:00
*/
2016-05-05 07:57:53 +03:00
status = acpi_os_write_port ( ( acpi_io_address ) reset_reg - > address ,
acpi_gbl_FADT . reset_value ,
ACPI_RESET_REGISTER_WIDTH ) ;
2009-08-13 09:42:19 +04:00
} else {
/* Write the reset value to the reset register */
status = acpi_hw_write ( acpi_gbl_FADT . reset_value , reset_reg ) ;
}
2008-12-30 06:11:57 +03:00
return_ACPI_STATUS ( status ) ;
}
ACPI_EXPORT_SYMBOL ( acpi_reset )
2008-12-30 06:04:48 +03:00
/******************************************************************************
*
* FUNCTION : acpi_read
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : value - Where the value is returned
* reg - GAS register structure
2008-12-30 06:04:48 +03:00
*
* RETURN : Status
*
* DESCRIPTION : Read from either memory or IO space .
*
2009-06-24 05:44:06 +04:00
* LIMITATIONS : < These limitations also apply to acpi_write >
* bit_width must be exactly 8 , 16 , 32 , or 64.
2012-07-12 05:40:10 +04:00
* space_ID must be system_memory or system_IO .
2009-06-24 05:44:06 +04:00
* bit_offset and access_width are currently ignored , as there has
* not been a need to implement these .
*
2008-12-30 06:04:48 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-24 05:44:06 +04:00
acpi_status acpi_read ( u64 * return_value , struct acpi_generic_address * reg )
2008-12-30 06:04:48 +03:00
{
acpi_status status ;
ACPI_FUNCTION_NAME ( acpi_read ) ;
2017-09-20 05:00:11 +03:00
status = acpi_hw_read ( return_value , reg ) ;
return ( status ) ;
2008-12-30 06:04:48 +03:00
}
ACPI_EXPORT_SYMBOL ( acpi_read )
/******************************************************************************
*
* FUNCTION : acpi_write
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : value - Value to be written
* reg - GAS register structure
2008-12-30 06:04:48 +03:00
*
* RETURN : Status
*
* DESCRIPTION : Write to either memory or IO space .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-24 05:44:06 +04:00
acpi_status acpi_write ( u64 value , struct acpi_generic_address * reg )
2008-12-30 06:04:48 +03:00
{
acpi_status status ;
ACPI_FUNCTION_NAME ( acpi_write ) ;
2017-09-20 05:00:11 +03:00
status = acpi_hw_write ( value , reg ) ;
2008-12-30 06:04:48 +03:00
return ( status ) ;
}
ACPI_EXPORT_SYMBOL ( acpi_write )
2012-02-14 14:14:27 +04:00
# if (!ACPI_REDUCED_HARDWARE)
2008-12-30 06:04:48 +03:00
/*******************************************************************************
*
2009-02-23 10:02:07 +03:00
* FUNCTION : acpi_read_bit_register
2008-12-30 06:04:48 +03:00
*
2009-02-18 10:10:07 +03:00
* PARAMETERS : register_id - ID of ACPI Bit Register to access
* return_value - Value that was read from the register ,
* normalized to bit position zero .
2008-12-30 06:04:48 +03:00
*
2009-02-18 10:10:07 +03:00
* RETURN : Status and the value read from the specified Register . Value
2008-12-30 06:04:48 +03:00
* returned is normalized to bit0 ( is shifted all the way right )
*
* DESCRIPTION : ACPI bit_register read function . Does not acquire the HW lock .
*
2009-02-18 10:10:07 +03:00
* SUPPORTS : Bit fields in PM1 Status , PM1 Enable , PM1 Control , and
* PM2 Control .
*
* Note : The hardware lock is not required when reading the ACPI bit registers
* since almost all of them are single bit and it does not matter that
* the parent hardware register can be split across two physical
* registers . The only multi - bit field is SLP_TYP in the PM1 control
* register , but this field does not cross an 8 - bit boundary ( nor does
* it make much sense to actually read this field . )
*
2008-12-30 06:04:48 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-02-23 10:02:07 +03:00
acpi_status acpi_read_bit_register ( u32 register_id , u32 * return_value )
2008-12-30 06:04:48 +03:00
{
struct acpi_bit_register_info * bit_reg_info ;
2009-02-18 11:01:04 +03:00
u32 register_value ;
u32 value ;
2008-12-30 06:04:48 +03:00
acpi_status status ;
2009-02-18 11:01:04 +03:00
ACPI_FUNCTION_TRACE_U32 ( acpi_read_bit_register , register_id ) ;
2008-12-30 06:04:48 +03:00
/* Get the info structure corresponding to the requested ACPI Register */
bit_reg_info = acpi_hw_get_bit_register_info ( register_id ) ;
if ( ! bit_reg_info ) {
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
}
2009-02-18 10:10:07 +03:00
/* Read the entire parent register */
2008-12-30 06:04:48 +03:00
status = acpi_hw_register_read ( bit_reg_info - > parent_register ,
& register_value ) ;
2009-02-18 11:01:04 +03:00
if ( ACPI_FAILURE ( status ) ) {
return_ACPI_STATUS ( status ) ;
}
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
/* Normalize the value that was read, mask off other bits */
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
value = ( ( register_value & bit_reg_info - > access_bit_mask )
> > bit_reg_info - > bit_position ) ;
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_IO ,
" BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X \n " ,
register_id , bit_reg_info - > parent_register ,
register_value , value ) ) ;
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
* return_value = value ;
return_ACPI_STATUS ( AE_OK ) ;
2008-12-30 06:04:48 +03:00
}
2009-02-23 10:02:07 +03:00
ACPI_EXPORT_SYMBOL ( acpi_read_bit_register )
2008-12-30 06:04:48 +03:00
/*******************************************************************************
*
2009-02-23 10:02:07 +03:00
* FUNCTION : acpi_write_bit_register
2008-12-30 06:04:48 +03:00
*
2009-02-18 10:10:07 +03:00
* PARAMETERS : register_id - ID of ACPI Bit Register to access
2012-12-19 09:36:49 +04:00
* value - Value to write to the register , in bit
2011-11-29 08:31:00 +04:00
* position zero . The bit is automatically
2009-02-18 10:10:07 +03:00
* shifted to the correct position .
2008-12-30 06:04:48 +03:00
*
* RETURN : Status
*
2009-02-18 10:10:07 +03:00
* DESCRIPTION : ACPI Bit Register write function . Acquires the hardware lock
* since most operations require a read / modify / write sequence .
*
* SUPPORTS : Bit fields in PM1 Status , PM1 Enable , PM1 Control , and
* PM2 Control .
2008-12-30 06:04:48 +03:00
*
2009-02-18 11:01:04 +03:00
* Note that at this level , the fact that there may be actually two
* hardware registers ( A and B - and B may not exist ) is abstracted .
*
2008-12-30 06:04:48 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-02-23 10:02:07 +03:00
acpi_status acpi_write_bit_register ( u32 register_id , u32 value )
2008-12-30 06:04:48 +03:00
{
struct acpi_bit_register_info * bit_reg_info ;
acpi_cpu_flags lock_flags ;
2009-02-18 11:01:04 +03:00
u32 register_value ;
acpi_status status = AE_OK ;
2008-12-30 06:04:48 +03:00
2009-02-23 10:02:07 +03:00
ACPI_FUNCTION_TRACE_U32 ( acpi_write_bit_register , register_id ) ;
2008-12-30 06:04:48 +03:00
/* Get the info structure corresponding to the requested ACPI Register */
bit_reg_info = acpi_hw_get_bit_register_info ( register_id ) ;
if ( ! bit_reg_info ) {
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
}
2018-04-25 17:28:27 +03:00
lock_flags = acpi_os_acquire_raw_lock ( acpi_gbl_hardware_lock ) ;
2008-12-30 06:04:48 +03:00
/*
2009-02-18 11:01:04 +03:00
* At this point , we know that the parent register is one of the
* following : PM1 Status , PM1 Enable , PM1 Control , or PM2 Control
2008-12-30 06:04:48 +03:00
*/
2009-02-18 11:01:04 +03:00
if ( bit_reg_info - > parent_register ! = ACPI_REGISTER_PM1_STATUS ) {
2008-12-30 06:04:48 +03:00
/*
2009-02-18 11:01:04 +03:00
* 1 ) Case for PM1 Enable , PM1 Control , and PM2 Control
*
* Perform a register read to preserve the bits that we are not
* interested in
2008-12-30 06:04:48 +03:00
*/
2009-02-18 11:01:04 +03:00
status = acpi_hw_register_read ( bit_reg_info - > parent_register ,
2008-12-30 06:04:48 +03:00
& register_value ) ;
if ( ACPI_FAILURE ( status ) ) {
goto unlock_and_exit ;
}
2009-02-18 11:01:04 +03:00
/*
* Insert the input bit into the value that was just read
* and write the register
*/
2008-12-30 06:04:48 +03:00
ACPI_REGISTER_INSERT_VALUE ( register_value ,
bit_reg_info - > bit_position ,
bit_reg_info - > access_bit_mask ,
value ) ;
2009-02-18 11:01:04 +03:00
status = acpi_hw_register_write ( bit_reg_info - > parent_register ,
register_value ) ;
} else {
/*
* 2 ) Case for PM1 Status
*
* The Status register is different from the rest . Clear an event
* by writing 1 , writing 0 has no effect . So , the only relevant
* information is the single bit we ' re interested in , all others
* should be written as 0 so they will be left unchanged .
*/
register_value = ACPI_REGISTER_PREPARE_BITS ( value ,
bit_reg_info - >
bit_position ,
bit_reg_info - >
access_bit_mask ) ;
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
/* No need to write the register if value is all zeros */
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
if ( register_value ) {
status =
acpi_hw_register_write ( ACPI_REGISTER_PM1_STATUS ,
register_value ) ;
}
2008-12-30 06:04:48 +03:00
}
2009-02-18 11:01:04 +03:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_IO ,
" BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X \n " ,
register_id , bit_reg_info - > parent_register , value ,
register_value ) ) ;
2008-12-30 06:04:48 +03:00
2009-02-18 11:01:04 +03:00
unlock_and_exit :
2008-12-30 06:04:48 +03:00
2018-04-25 17:28:27 +03:00
acpi_os_release_raw_lock ( acpi_gbl_hardware_lock , lock_flags ) ;
2008-12-30 06:04:48 +03:00
return_ACPI_STATUS ( status ) ;
}
2009-02-23 10:02:07 +03:00
ACPI_EXPORT_SYMBOL ( acpi_write_bit_register )
2012-02-14 14:14:27 +04:00
# endif /* !ACPI_REDUCED_HARDWARE */
2008-12-30 06:04:48 +03:00
/*******************************************************************************
*
* FUNCTION : acpi_get_sleep_type_data
*
* PARAMETERS : sleep_state - Numeric sleep state
* * sleep_type_a - Where SLP_TYPa is returned
* * sleep_type_b - Where SLP_TYPb is returned
*
2013-01-25 09:41:00 +04:00
* RETURN : Status
*
* DESCRIPTION : Obtain the SLP_TYPa and SLP_TYPb values for the requested
* sleep state via the appropriate \ _Sx object .
*
* The sleep state package returned from the corresponding \ _Sx_ object
* must contain at least one integer .
*
* March 2005 :
* Added support for a package that contains two integers . This
* goes against the ACPI specification which defines this object as a
* package with one encoded DWORD integer . However , existing practice
* by many BIOS vendors is to return a package with 2 or more integer
* elements , at least one per sleep type ( A / B ) .
2008-12-30 06:04:48 +03:00
*
2013-01-25 09:41:00 +04:00
* January 2013 :
* Therefore , we must be prepared to accept a package with either a
* single integer or multiple integers .
*
* The single integer DWORD format is as follows :
* BYTE 0 - Value for the PM1A SLP_TYP register
* BYTE 1 - Value for the PM1B SLP_TYP register
* BYTE 2 - 3 - Reserved
*
* The dual integer format is as follows :
* Integer 0 - Value for the PM1A SLP_TYP register
* Integer 1 - Value for the PM1A SLP_TYP register
2008-12-30 06:04:48 +03:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
acpi_get_sleep_type_data ( u8 sleep_state , u8 * sleep_type_a , u8 * sleep_type_b )
{
2013-01-25 09:41:00 +04:00
acpi_status status ;
2008-12-30 06:04:48 +03:00
struct acpi_evaluate_info * info ;
2013-01-25 09:41:00 +04:00
union acpi_operand_object * * elements ;
2008-12-30 06:04:48 +03:00
ACPI_FUNCTION_TRACE ( acpi_get_sleep_type_data ) ;
/* Validate parameters */
if ( ( sleep_state > ACPI_S_STATES_MAX ) | | ! sleep_type_a | | ! sleep_type_b ) {
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
}
/* Allocate the evaluation information block */
info = ACPI_ALLOCATE_ZEROED ( sizeof ( struct acpi_evaluate_info ) ) ;
if ( ! info ) {
return_ACPI_STATUS ( AE_NO_MEMORY ) ;
}
2013-01-25 09:41:00 +04:00
/*
* Evaluate the \ _Sx namespace object containing the register values
* for this state
*/
2016-03-24 04:40:40 +03:00
info - > relative_pathname = acpi_gbl_sleep_state_names [ sleep_state ] ;
2015-12-29 08:52:41 +03:00
2008-12-30 06:04:48 +03:00
status = acpi_ns_evaluate ( info ) ;
if ( ACPI_FAILURE ( status ) ) {
2015-12-29 08:52:41 +03:00
if ( status = = AE_NOT_FOUND ) {
/* The _Sx states are optional, ignore NOT_FOUND */
goto final_cleanup ;
}
goto warning_cleanup ;
2008-12-30 06:04:48 +03:00
}
/* Must have a return object */
if ( ! info - > return_object ) {
ACPI_ERROR ( ( AE_INFO , " No Sleep State object returned from [%s] " ,
2013-05-30 06:00:01 +04:00
info - > relative_pathname ) ) ;
2013-01-25 09:41:00 +04:00
status = AE_AML_NO_RETURN_VALUE ;
2015-12-29 08:52:41 +03:00
goto warning_cleanup ;
2008-12-30 06:04:48 +03:00
}
2013-01-25 09:41:00 +04:00
/* Return object must be of type Package */
2008-12-30 06:04:48 +03:00
2013-01-25 09:41:00 +04:00
if ( info - > return_object - > common . type ! = ACPI_TYPE_PACKAGE ) {
2008-12-30 06:04:48 +03:00
ACPI_ERROR ( ( AE_INFO ,
" Sleep State return object is not a Package " ) ) ;
status = AE_AML_OPERAND_TYPE ;
2015-12-29 08:52:41 +03:00
goto return_value_cleanup ;
2008-12-30 06:04:48 +03:00
}
/*
2013-01-25 09:41:00 +04:00
* Any warnings about the package length or the object types have
* already been issued by the predefined name module - - there is no
* need to repeat them here .
2008-12-30 06:04:48 +03:00
*/
2013-01-25 09:41:00 +04:00
elements = info - > return_object - > package . elements ;
switch ( info - > return_object - > package . count ) {
case 0 :
2013-06-08 04:58:14 +04:00
2013-01-25 09:41:00 +04:00
status = AE_AML_PACKAGE_LIMIT ;
break ;
case 1 :
2013-06-08 04:58:14 +04:00
2013-01-25 09:41:00 +04:00
if ( elements [ 0 ] - > common . type ! = ACPI_TYPE_INTEGER ) {
status = AE_AML_OPERAND_TYPE ;
break ;
}
2008-12-30 06:04:48 +03:00
2013-01-25 09:41:00 +04:00
/* A valid _Sx_ package with one integer */
2008-12-30 06:04:48 +03:00
2013-01-25 09:41:00 +04:00
* sleep_type_a = ( u8 ) elements [ 0 ] - > integer . value ;
* sleep_type_b = ( u8 ) ( elements [ 0 ] - > integer . value > > 8 ) ;
break ;
2008-12-30 06:04:48 +03:00
2013-01-25 09:41:00 +04:00
case 2 :
default :
2013-06-08 04:58:14 +04:00
2013-01-25 09:41:00 +04:00
if ( ( elements [ 0 ] - > common . type ! = ACPI_TYPE_INTEGER ) | |
( elements [ 1 ] - > common . type ! = ACPI_TYPE_INTEGER ) ) {
status = AE_AML_OPERAND_TYPE ;
break ;
}
2008-12-30 06:04:48 +03:00
2013-01-25 09:41:00 +04:00
/* A valid _Sx_ package with two integers */
* sleep_type_a = ( u8 ) elements [ 0 ] - > integer . value ;
* sleep_type_b = ( u8 ) elements [ 1 ] - > integer . value ;
break ;
2008-12-30 06:04:48 +03:00
}
2015-12-29 08:52:41 +03:00
return_value_cleanup :
2008-12-30 06:04:48 +03:00
acpi_ut_remove_reference ( info - > return_object ) ;
2015-12-29 08:52:41 +03:00
warning_cleanup :
2013-01-25 09:41:00 +04:00
if ( ACPI_FAILURE ( status ) ) {
ACPI_EXCEPTION ( ( AE_INFO , status ,
" While evaluating Sleep State [%s] " ,
2013-05-30 06:00:01 +04:00
info - > relative_pathname ) ) ;
2013-01-25 09:41:00 +04:00
}
2015-12-29 08:52:41 +03:00
final_cleanup :
2008-12-30 06:04:48 +03:00
ACPI_FREE ( info ) ;
return_ACPI_STATUS ( status ) ;
}
ACPI_EXPORT_SYMBOL ( acpi_get_sleep_type_data )