2019-05-27 08:55:05 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-03-07 11:03:27 +05:30
/*
* PowerNV sensor code
*
* Copyright ( C ) 2013 IBM
*/
# include <linux/delay.h>
2014-11-05 16:45:14 +05:30
# include <linux/of_platform.h>
2014-03-07 11:03:27 +05:30
# include <asm/opal.h>
2014-11-05 16:45:14 +05:30
# include <asm/machdep.h>
2014-03-07 11:03:27 +05:30
/*
* This will return sensor information to driver based on the requested sensor
* handle . A handle is an opaque id for the powernv , read by the driver from the
* device tree . .
*/
int opal_get_sensor_data ( u32 sensor_hndl , u32 * sensor_data )
{
int ret , token ;
struct opal_msg msg ;
2014-03-28 16:34:10 +11:00
__be32 data ;
2014-03-07 11:03:27 +05:30
token = opal_async_get_token_interruptible ( ) ;
2017-11-03 13:41:43 +11:00
if ( token < 0 )
return token ;
2014-03-07 11:03:27 +05:30
2014-03-28 16:34:10 +11:00
ret = opal_sensor_read ( sensor_hndl , token , & data ) ;
2015-03-30 12:06:10 +02:00
switch ( ret ) {
case OPAL_ASYNC_COMPLETION :
ret = opal_async_wait_response ( token , & msg ) ;
if ( ret ) {
pr_err ( " %s: Failed to wait for the async response, %d \n " ,
__func__ , ret ) ;
2017-11-03 13:41:43 +11:00
goto out ;
2015-03-30 12:06:10 +02:00
}
2014-03-07 11:03:27 +05:30
2016-06-29 13:38:38 +10:00
ret = opal_error_code ( opal_get_async_rc ( msg ) ) ;
2015-03-30 12:06:10 +02:00
* sensor_data = be32_to_cpu ( data ) ;
break ;
2014-03-07 11:03:27 +05:30
2015-03-30 12:06:10 +02:00
case OPAL_SUCCESS :
ret = 0 ;
* sensor_data = be32_to_cpu ( data ) ;
break ;
2017-03-10 17:27:32 +05:30
case OPAL_WRONG_STATE :
ret = - EIO ;
break ;
2015-03-30 12:06:10 +02:00
default :
ret = opal_error_code ( ret ) ;
break ;
}
2014-03-07 11:03:27 +05:30
out :
2017-11-03 13:41:43 +11:00
opal_async_release_token ( token ) ;
2014-03-07 11:03:27 +05:30
return ret ;
}
EXPORT_SYMBOL_GPL ( opal_get_sensor_data ) ;
2014-11-05 16:45:14 +05:30
2018-05-07 15:55:36 +05:30
int opal_get_sensor_data_u64 ( u32 sensor_hndl , u64 * sensor_data )
{
int ret , token ;
struct opal_msg msg ;
__be64 data ;
if ( ! opal_check_token ( OPAL_SENSOR_READ_U64 ) ) {
u32 sdata ;
ret = opal_get_sensor_data ( sensor_hndl , & sdata ) ;
if ( ! ret )
* sensor_data = sdata ;
return ret ;
}
token = opal_async_get_token_interruptible ( ) ;
if ( token < 0 )
return token ;
ret = opal_sensor_read_u64 ( sensor_hndl , token , & data ) ;
switch ( ret ) {
case OPAL_ASYNC_COMPLETION :
ret = opal_async_wait_response ( token , & msg ) ;
if ( ret ) {
pr_err ( " %s: Failed to wait for the async response, %d \n " ,
__func__ , ret ) ;
goto out_token ;
}
ret = opal_error_code ( opal_get_async_rc ( msg ) ) ;
* sensor_data = be64_to_cpu ( data ) ;
break ;
case OPAL_SUCCESS :
ret = 0 ;
* sensor_data = be64_to_cpu ( data ) ;
break ;
case OPAL_WRONG_STATE :
ret = - EIO ;
break ;
default :
ret = opal_error_code ( ret ) ;
break ;
}
out_token :
opal_async_release_token ( token ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( opal_get_sensor_data_u64 ) ;
2015-05-15 14:06:36 +10:00
int __init opal_sensor_init ( void )
2014-11-05 16:45:14 +05:30
{
struct platform_device * pdev ;
struct device_node * sensor ;
sensor = of_find_node_by_path ( " /ibm,opal/sensors " ) ;
if ( ! sensor ) {
pr_err ( " Opal node 'sensors' not found \n " ) ;
return - ENODEV ;
}
pdev = of_platform_device_create ( sensor , " opal-sensor " , NULL ) ;
of_node_put ( sensor ) ;
return PTR_ERR_OR_ZERO ( pdev ) ;
}