2014-11-04 03:28:56 +03:00
/*
* property . c - Unified device property interface .
*
* Copyright ( C ) 2014 , Intel Corporation
* Authors : Rafael J . Wysocki < rafael . j . wysocki @ intel . com >
* Mika Westerberg < mika . westerberg @ linux . intel . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/acpi.h>
2015-04-03 17:05:11 +03:00
# include <linux/export.h>
# include <linux/kernel.h>
2014-11-04 03:28:56 +03:00
# include <linux/of.h>
2015-06-10 19:08:54 +03:00
# include <linux/of_address.h>
2015-04-03 17:05:11 +03:00
# include <linux/property.h>
2015-08-13 01:06:26 +03:00
# include <linux/etherdevice.h>
# include <linux/phy.h>
2015-04-03 17:05:11 +03:00
/**
* device_add_property_set - Add a collection of properties to a device object .
* @ dev : Device to add properties to .
* @ pset : Collection of properties to add .
*
* Associate a collection of device properties represented by @ pset with @ dev
* as its secondary firmware node .
*/
void device_add_property_set ( struct device * dev , struct property_set * pset )
{
2015-08-05 16:51:11 +03:00
if ( ! pset )
return ;
2015-04-03 17:05:11 +03:00
2015-08-05 16:51:11 +03:00
pset - > fwnode . type = FWNODE_PDATA ;
2015-04-03 17:05:11 +03:00
set_secondary_fwnode ( dev , & pset - > fwnode ) ;
}
EXPORT_SYMBOL_GPL ( device_add_property_set ) ;
2015-11-30 18:11:30 +03:00
static inline bool is_pset_node ( struct fwnode_handle * fwnode )
2015-04-03 17:05:11 +03:00
{
return fwnode & & fwnode - > type = = FWNODE_PDATA ;
}
2015-11-30 18:11:30 +03:00
static inline struct property_set * to_pset_node ( struct fwnode_handle * fwnode )
2015-04-03 17:05:11 +03:00
{
2015-11-30 18:11:30 +03:00
return is_pset_node ( fwnode ) ?
2015-04-03 17:05:11 +03:00
container_of ( fwnode , struct property_set , fwnode ) : NULL ;
}
static struct property_entry * pset_prop_get ( struct property_set * pset ,
const char * name )
{
struct property_entry * prop ;
if ( ! pset | | ! pset - > properties )
return NULL ;
for ( prop = pset - > properties ; prop - > name ; prop + + )
if ( ! strcmp ( name , prop - > name ) )
return prop ;
return NULL ;
}
2015-11-30 18:11:31 +03:00
static void * pset_prop_find ( struct property_set * pset , const char * propname ,
size_t length )
2015-04-03 17:05:11 +03:00
{
struct property_entry * prop ;
2015-11-30 18:11:31 +03:00
void * pointer ;
2015-04-03 17:05:11 +03:00
2015-11-30 18:11:31 +03:00
prop = pset_prop_get ( pset , propname ) ;
if ( ! prop )
return ERR_PTR ( - EINVAL ) ;
2015-11-30 18:11:32 +03:00
if ( prop - > is_array )
pointer = prop - > pointer . raw_data ;
else
pointer = & prop - > value . raw_data ;
2015-11-30 18:11:31 +03:00
if ( ! pointer )
return ERR_PTR ( - ENODATA ) ;
if ( length > prop - > length )
return ERR_PTR ( - EOVERFLOW ) ;
return pointer ;
}
static int pset_prop_read_u8_array ( struct property_set * pset ,
const char * propname ,
u8 * values , size_t nval )
{
void * pointer ;
size_t length = nval * sizeof ( * values ) ;
pointer = pset_prop_find ( pset , propname , length ) ;
if ( IS_ERR ( pointer ) )
return PTR_ERR ( pointer ) ;
memcpy ( values , pointer , length ) ;
return 0 ;
}
static int pset_prop_read_u16_array ( struct property_set * pset ,
const char * propname ,
u16 * values , size_t nval )
{
void * pointer ;
size_t length = nval * sizeof ( * values ) ;
pointer = pset_prop_find ( pset , propname , length ) ;
if ( IS_ERR ( pointer ) )
return PTR_ERR ( pointer ) ;
memcpy ( values , pointer , length ) ;
return 0 ;
}
static int pset_prop_read_u32_array ( struct property_set * pset ,
const char * propname ,
u32 * values , size_t nval )
{
void * pointer ;
size_t length = nval * sizeof ( * values ) ;
pointer = pset_prop_find ( pset , propname , length ) ;
if ( IS_ERR ( pointer ) )
return PTR_ERR ( pointer ) ;
memcpy ( values , pointer , length ) ;
return 0 ;
}
static int pset_prop_read_u64_array ( struct property_set * pset ,
const char * propname ,
u64 * values , size_t nval )
{
void * pointer ;
size_t length = nval * sizeof ( * values ) ;
pointer = pset_prop_find ( pset , propname , length ) ;
if ( IS_ERR ( pointer ) )
return PTR_ERR ( pointer ) ;
memcpy ( values , pointer , length ) ;
return 0 ;
}
static int pset_prop_count_elems_of_size ( struct property_set * pset ,
const char * propname , size_t length )
{
struct property_entry * prop ;
prop = pset_prop_get ( pset , propname ) ;
2015-04-03 17:05:11 +03:00
if ( ! prop )
return - EINVAL ;
2015-11-30 18:11:31 +03:00
return prop - > length / length ;
}
static int pset_prop_read_string_array ( struct property_set * pset ,
const char * propname ,
const char * * strings , size_t nval )
{
void * pointer ;
size_t length = nval * sizeof ( * strings ) ;
pointer = pset_prop_find ( pset , propname , length ) ;
if ( IS_ERR ( pointer ) )
return PTR_ERR ( pointer ) ;
memcpy ( strings , pointer , length ) ;
2015-04-03 17:05:11 +03:00
return 0 ;
}
2014-11-04 03:28:56 +03:00
2015-11-30 18:11:32 +03:00
static int pset_prop_read_string ( struct property_set * pset ,
const char * propname , const char * * strings )
{
struct property_entry * prop ;
const char * * pointer ;
prop = pset_prop_get ( pset , propname ) ;
if ( ! prop )
return - EINVAL ;
if ( ! prop - > is_string )
return - EILSEQ ;
if ( prop - > is_array ) {
pointer = prop - > pointer . str ;
if ( ! pointer )
return - ENODATA ;
} else {
pointer = & prop - > value . str ;
if ( * pointer & & strnlen ( * pointer , prop - > length ) > = prop - > length )
return - EILSEQ ;
}
* strings = * pointer ;
return 0 ;
}
2015-03-24 02:24:16 +03:00
static inline struct fwnode_handle * dev_fwnode ( struct device * dev )
{
return IS_ENABLED ( CONFIG_OF ) & & dev - > of_node ?
& dev - > of_node - > fwnode : dev - > fwnode ;
}
2014-11-04 03:28:56 +03:00
/**
* device_property_present - check if a property of a device is present
* @ dev : Device whose property is being checked
* @ propname : Name of the property
*
* Check if property @ propname is present in the device firmware description .
*/
bool device_property_present ( struct device * dev , const char * propname )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_present ( dev_fwnode ( dev ) , propname ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_present ) ;
2015-11-30 18:11:36 +03:00
static bool __fwnode_property_present ( struct fwnode_handle * fwnode ,
const char * propname )
2014-11-04 16:03:59 +03:00
{
if ( is_of_node ( fwnode ) )
2015-06-22 23:38:53 +03:00
return of_property_read_bool ( to_of_node ( fwnode ) , propname ) ;
2014-11-04 16:03:59 +03:00
else if ( is_acpi_node ( fwnode ) )
2015-08-27 05:40:05 +03:00
return ! acpi_node_prop_get ( fwnode , propname , NULL ) ;
2015-11-30 18:11:30 +03:00
else if ( is_pset_node ( fwnode ) )
return ! ! pset_prop_get ( to_pset_node ( fwnode ) , propname ) ;
2015-11-30 18:11:29 +03:00
return false ;
2014-11-04 16:03:59 +03:00
}
2015-11-30 18:11:36 +03:00
/**
* fwnode_property_present - check if a property of a firmware node is present
* @ fwnode : Firmware node whose property to check
* @ propname : Name of the property
*/
bool fwnode_property_present ( struct fwnode_handle * fwnode , const char * propname )
{
bool ret ;
ret = __fwnode_property_present ( fwnode , propname ) ;
if ( ret = = false & & fwnode - > secondary )
ret = __fwnode_property_present ( fwnode - > secondary , propname ) ;
return ret ;
}
2014-11-04 16:03:59 +03:00
EXPORT_SYMBOL_GPL ( fwnode_property_present ) ;
2014-11-04 03:28:56 +03:00
/**
* device_property_read_u8_array - return a u8 array property of a device
* @ dev : Device to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 03:28:56 +03:00
* @ nval : Size of the @ val array
*
* Function reads an array of u8 properties with @ propname from the device
* firmware description and stores them to @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 03:28:56 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected .
2015-08-27 06:27:04 +03:00
* % - ENXIO if no suitable firmware interface is present .
2014-11-04 03:28:56 +03:00
*/
int device_property_read_u8_array ( struct device * dev , const char * propname ,
u8 * val , size_t nval )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_read_u8_array ( dev_fwnode ( dev ) , propname , val , nval ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_read_u8_array ) ;
/**
* device_property_read_u16_array - return a u16 array property of a device
* @ dev : Device to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 03:28:56 +03:00
* @ nval : Size of the @ val array
*
* Function reads an array of u16 properties with @ propname from the device
* firmware description and stores them to @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 03:28:56 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected .
2015-08-27 06:27:04 +03:00
* % - ENXIO if no suitable firmware interface is present .
2014-11-04 03:28:56 +03:00
*/
int device_property_read_u16_array ( struct device * dev , const char * propname ,
u16 * val , size_t nval )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_read_u16_array ( dev_fwnode ( dev ) , propname , val , nval ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_read_u16_array ) ;
/**
* device_property_read_u32_array - return a u32 array property of a device
* @ dev : Device to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 03:28:56 +03:00
* @ nval : Size of the @ val array
*
* Function reads an array of u32 properties with @ propname from the device
* firmware description and stores them to @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 03:28:56 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected .
2015-08-27 06:27:04 +03:00
* % - ENXIO if no suitable firmware interface is present .
2014-11-04 03:28:56 +03:00
*/
int device_property_read_u32_array ( struct device * dev , const char * propname ,
u32 * val , size_t nval )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_read_u32_array ( dev_fwnode ( dev ) , propname , val , nval ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_read_u32_array ) ;
/**
* device_property_read_u64_array - return a u64 array property of a device
* @ dev : Device to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 03:28:56 +03:00
* @ nval : Size of the @ val array
*
* Function reads an array of u64 properties with @ propname from the device
* firmware description and stores them to @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 03:28:56 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected .
2015-08-27 06:27:04 +03:00
* % - ENXIO if no suitable firmware interface is present .
2014-11-04 03:28:56 +03:00
*/
int device_property_read_u64_array ( struct device * dev , const char * propname ,
u64 * val , size_t nval )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_read_u64_array ( dev_fwnode ( dev ) , propname , val , nval ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_read_u64_array ) ;
/**
* device_property_read_string_array - return a string array property of device
* @ dev : Device to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 03:28:56 +03:00
* @ nval : Size of the @ val array
*
* Function reads an array of string properties with @ propname from the device
* firmware description and stores them to @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 03:28:56 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO or % - EILSEQ if the property is not an array of strings ,
* % - EOVERFLOW if the size of the property is not as expected .
2015-08-27 06:27:04 +03:00
* % - ENXIO if no suitable firmware interface is present .
2014-11-04 03:28:56 +03:00
*/
int device_property_read_string_array ( struct device * dev , const char * propname ,
const char * * val , size_t nval )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_read_string_array ( dev_fwnode ( dev ) , propname , val , nval ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_read_string_array ) ;
/**
* device_property_read_string - return a string property of a device
* @ dev : Device to get the property of
* @ propname : Name of the property
* @ val : The value is stored here
*
* Function reads property @ propname from the device firmware description and
* stores the value into @ val if found . The value is checked to be a string .
*
* Return : % 0 if the property was found ( success ) ,
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO or % - EILSEQ if the property type is not a string .
2015-08-27 06:27:04 +03:00
* % - ENXIO if no suitable firmware interface is present .
2014-11-04 03:28:56 +03:00
*/
int device_property_read_string ( struct device * dev , const char * propname ,
const char * * val )
{
2015-03-24 02:24:16 +03:00
return fwnode_property_read_string ( dev_fwnode ( dev ) , propname , val ) ;
2014-11-04 03:28:56 +03:00
}
EXPORT_SYMBOL_GPL ( device_property_read_string ) ;
2014-11-04 16:03:59 +03:00
2015-09-14 17:37:35 +03:00
/**
* device_property_match_string - find a string in an array and return index
* @ dev : Device to get the property of
* @ propname : Name of the property holding the array
* @ string : String to look for
*
* Find a given string in a string array and if it is found return the
* index back .
*
* Return : % 0 if the property was found ( success ) ,
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of strings ,
* % - ENXIO if no suitable firmware interface is present .
*/
int device_property_match_string ( struct device * dev , const char * propname ,
const char * string )
{
return fwnode_property_match_string ( dev_fwnode ( dev ) , propname , string ) ;
}
EXPORT_SYMBOL_GPL ( device_property_match_string ) ;
2015-11-30 18:11:34 +03:00
# define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
( val ) ? of_property_read_ # # type # # _array ( ( node ) , ( propname ) , ( val ) , ( nval ) ) \
2015-03-24 02:24:16 +03:00
: of_property_count_elems_of_size ( ( node ) , ( propname ) , sizeof ( type ) )
2015-11-30 18:11:31 +03:00
# define PSET_PROP_READ_ARRAY(node, propname, type, val, nval) \
( val ) ? pset_prop_read_ # # type # # _array ( ( node ) , ( propname ) , ( val ) , ( nval ) ) \
: pset_prop_count_elems_of_size ( ( node ) , ( propname ) , sizeof ( type ) )
2015-11-30 18:11:36 +03:00
# define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
2015-11-30 18:11:34 +03:00
( { \
int _ret_ ; \
if ( is_of_node ( _fwnode_ ) ) \
_ret_ = OF_DEV_PROP_READ_ARRAY ( to_of_node ( _fwnode_ ) , _propname_ , \
_type_ , _val_ , _nval_ ) ; \
else if ( is_acpi_node ( _fwnode_ ) ) \
_ret_ = acpi_node_prop_read ( _fwnode_ , _propname_ , _proptype_ , \
_val_ , _nval_ ) ; \
2015-11-30 18:11:30 +03:00
else if ( is_pset_node ( _fwnode_ ) ) \
2015-11-30 18:11:31 +03:00
_ret_ = PSET_PROP_READ_ARRAY ( to_pset_node ( _fwnode_ ) , _propname_ , \
_type_ , _val_ , _nval_ ) ; \
2015-11-30 18:11:34 +03:00
else \
_ret_ = - ENXIO ; \
_ret_ ; \
2014-11-04 16:03:59 +03:00
} )
2015-11-30 18:11:36 +03:00
# define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
( { \
int _ret_ ; \
_ret_ = FWNODE_PROP_READ ( _fwnode_ , _propname_ , _type_ , _proptype_ , \
_val_ , _nval_ ) ; \
if ( _ret_ = = - EINVAL & & _fwnode_ - > secondary ) \
_ret_ = FWNODE_PROP_READ ( _fwnode_ - > secondary , _propname_ , _type_ , \
_proptype_ , _val_ , _nval_ ) ; \
_ret_ ; \
} )
2014-11-04 16:03:59 +03:00
/**
* fwnode_property_read_u8_array - return a u8 array property of firmware node
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 16:03:59 +03:00
* @ nval : Size of the @ val array
*
* Read an array of u8 properties with @ propname from @ fwnode and stores them to
* @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 16:03:59 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_read_u8_array ( struct fwnode_handle * fwnode ,
const char * propname , u8 * val , size_t nval )
{
return FWNODE_PROP_READ_ARRAY ( fwnode , propname , u8 , DEV_PROP_U8 ,
val , nval ) ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_u8_array ) ;
/**
* fwnode_property_read_u16_array - return a u16 array property of firmware node
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 16:03:59 +03:00
* @ nval : Size of the @ val array
*
* Read an array of u16 properties with @ propname from @ fwnode and store them to
* @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 16:03:59 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_read_u16_array ( struct fwnode_handle * fwnode ,
const char * propname , u16 * val , size_t nval )
{
return FWNODE_PROP_READ_ARRAY ( fwnode , propname , u16 , DEV_PROP_U16 ,
val , nval ) ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_u16_array ) ;
/**
* fwnode_property_read_u32_array - return a u32 array property of firmware node
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 16:03:59 +03:00
* @ nval : Size of the @ val array
*
* Read an array of u32 properties with @ propname from @ fwnode store them to
* @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 16:03:59 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_read_u32_array ( struct fwnode_handle * fwnode ,
const char * propname , u32 * val , size_t nval )
{
return FWNODE_PROP_READ_ARRAY ( fwnode , propname , u32 , DEV_PROP_U32 ,
val , nval ) ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_u32_array ) ;
/**
* fwnode_property_read_u64_array - return a u64 array property firmware node
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 16:03:59 +03:00
* @ nval : Size of the @ val array
*
* Read an array of u64 properties with @ propname from @ fwnode and store them to
* @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 16:03:59 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of numbers ,
* % - EOVERFLOW if the size of the property is not as expected ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_read_u64_array ( struct fwnode_handle * fwnode ,
const char * propname , u64 * val , size_t nval )
{
return FWNODE_PROP_READ_ARRAY ( fwnode , propname , u64 , DEV_PROP_U64 ,
val , nval ) ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_u64_array ) ;
2015-11-30 18:11:36 +03:00
static int __fwnode_property_read_string_array ( struct fwnode_handle * fwnode ,
const char * propname ,
const char * * val , size_t nval )
{
if ( is_of_node ( fwnode ) )
return val ?
of_property_read_string_array ( to_of_node ( fwnode ) ,
propname , val , nval ) :
of_property_count_strings ( to_of_node ( fwnode ) , propname ) ;
else if ( is_acpi_node ( fwnode ) )
return acpi_node_prop_read ( fwnode , propname , DEV_PROP_STRING ,
val , nval ) ;
else if ( is_pset_node ( fwnode ) )
return val ?
pset_prop_read_string_array ( to_pset_node ( fwnode ) ,
propname , val , nval ) :
pset_prop_count_elems_of_size ( to_pset_node ( fwnode ) ,
propname ,
sizeof ( const char * ) ) ;
return - ENXIO ;
}
static int __fwnode_property_read_string ( struct fwnode_handle * fwnode ,
const char * propname , const char * * val )
{
if ( is_of_node ( fwnode ) )
return of_property_read_string ( to_of_node ( fwnode ) , propname , val ) ;
else if ( is_acpi_node ( fwnode ) )
return acpi_node_prop_read ( fwnode , propname , DEV_PROP_STRING ,
val , 1 ) ;
else if ( is_pset_node ( fwnode ) )
return pset_prop_read_string ( to_pset_node ( fwnode ) , propname , val ) ;
return - ENXIO ;
}
2014-11-04 16:03:59 +03:00
/**
* fwnode_property_read_string_array - return string array property of a node
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property
2015-03-17 10:58:58 +03:00
* @ val : The values are stored here or % NULL to return the number of values
2014-11-04 16:03:59 +03:00
* @ nval : Size of the @ val array
*
* Read an string list property @ propname from the given firmware node and store
* them to @ val if found .
*
2015-03-17 10:58:58 +03:00
* Return : number of values if @ val was % NULL ,
* % 0 if the property was found ( success ) ,
2014-11-04 16:03:59 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of strings ,
* % - EOVERFLOW if the size of the property is not as expected ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_read_string_array ( struct fwnode_handle * fwnode ,
const char * propname , const char * * val ,
size_t nval )
{
2015-11-30 18:11:36 +03:00
int ret ;
ret = __fwnode_property_read_string_array ( fwnode , propname , val , nval ) ;
if ( ret = = - EINVAL & & fwnode - > secondary )
ret = __fwnode_property_read_string_array ( fwnode - > secondary ,
propname , val , nval ) ;
return ret ;
2014-11-04 16:03:59 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_string_array ) ;
/**
* fwnode_property_read_string - return a string property of a firmware node
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property
* @ val : The value is stored here
*
* Read property @ propname from the given firmware node and store the value into
* @ val if found . The value is checked to be a string .
*
* Return : % 0 if the property was found ( success ) ,
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO or % - EILSEQ if the property is not a string ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_read_string ( struct fwnode_handle * fwnode ,
const char * propname , const char * * val )
{
2015-11-30 18:11:36 +03:00
int ret ;
ret = __fwnode_property_read_string ( fwnode , propname , val ) ;
if ( ret = = - EINVAL & & fwnode - > secondary )
ret = __fwnode_property_read_string ( fwnode - > secondary ,
propname , val ) ;
return ret ;
2014-11-04 16:03:59 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_string ) ;
2015-09-14 17:37:35 +03:00
/**
* fwnode_property_match_string - find a string in an array and return index
* @ fwnode : Firmware node to get the property of
* @ propname : Name of the property holding the array
* @ string : String to look for
*
* Find a given string in a string array and if it is found return the
* index back .
*
* Return : % 0 if the property was found ( success ) ,
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
* % - EPROTO if the property is not an array of strings ,
* % - ENXIO if no suitable firmware interface is present .
*/
int fwnode_property_match_string ( struct fwnode_handle * fwnode ,
const char * propname , const char * string )
{
const char * * values ;
int nval , ret , i ;
nval = fwnode_property_read_string_array ( fwnode , propname , NULL , 0 ) ;
if ( nval < 0 )
return nval ;
values = kcalloc ( nval , sizeof ( * values ) , GFP_KERNEL ) ;
if ( ! values )
return - ENOMEM ;
ret = fwnode_property_read_string_array ( fwnode , propname , values , nval ) ;
if ( ret < 0 )
goto out ;
ret = - ENODATA ;
for ( i = 0 ; i < nval ; i + + ) {
if ( ! strcmp ( values [ i ] , string ) ) {
ret = i ;
break ;
}
}
out :
kfree ( values ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_match_string ) ;
2014-11-04 16:03:59 +03:00
/**
* device_get_next_child_node - Return the next child node handle for a device
* @ dev : Device to find the next child node for .
* @ child : Handle to one of the device ' s child nodes or a null handle .
*/
struct fwnode_handle * device_get_next_child_node ( struct device * dev ,
struct fwnode_handle * child )
{
if ( IS_ENABLED ( CONFIG_OF ) & & dev - > of_node ) {
struct device_node * node ;
2015-06-22 23:38:53 +03:00
node = of_get_next_available_child ( dev - > of_node , to_of_node ( child ) ) ;
2014-11-04 16:03:59 +03:00
if ( node )
return & node - > fwnode ;
} else if ( IS_ENABLED ( CONFIG_ACPI ) ) {
2015-08-27 05:42:33 +03:00
return acpi_get_next_subnode ( dev , child ) ;
2014-11-04 16:03:59 +03:00
}
return NULL ;
}
EXPORT_SYMBOL_GPL ( device_get_next_child_node ) ;
/**
* fwnode_handle_put - Drop reference to a device node
* @ fwnode : Pointer to the device node to drop the reference to .
*
* This has to be used when terminating device_for_each_child_node ( ) iteration
* with break or return to prevent stale device node references from being left
* behind .
*/
void fwnode_handle_put ( struct fwnode_handle * fwnode )
{
if ( is_of_node ( fwnode ) )
2015-06-22 23:38:53 +03:00
of_node_put ( to_of_node ( fwnode ) ) ;
2014-11-04 16:03:59 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_handle_put ) ;
/**
* device_get_child_node_count - return the number of child nodes for device
* @ dev : Device to cound the child nodes for
*/
unsigned int device_get_child_node_count ( struct device * dev )
{
struct fwnode_handle * child ;
unsigned int count = 0 ;
device_for_each_child_node ( dev , child )
count + + ;
return count ;
}
EXPORT_SYMBOL_GPL ( device_get_child_node_count ) ;
2015-06-10 19:08:54 +03:00
2015-10-29 01:50:49 +03:00
bool device_dma_supported ( struct device * dev )
{
/* For DT, this is always supported.
* For ACPI , this depends on CCA , which
* is determined by the acpi_dma_supported ( ) .
*/
if ( IS_ENABLED ( CONFIG_OF ) & & dev - > of_node )
return true ;
return acpi_dma_supported ( ACPI_COMPANION ( dev ) ) ;
}
EXPORT_SYMBOL_GPL ( device_dma_supported ) ;
enum dev_dma_attr device_get_dma_attr ( struct device * dev )
{
enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED ;
if ( IS_ENABLED ( CONFIG_OF ) & & dev - > of_node ) {
if ( of_dma_is_coherent ( dev - > of_node ) )
attr = DEV_DMA_COHERENT ;
else
attr = DEV_DMA_NON_COHERENT ;
} else
attr = acpi_get_dma_attr ( ACPI_COMPANION ( dev ) ) ;
return attr ;
}
EXPORT_SYMBOL_GPL ( device_get_dma_attr ) ;
2015-08-13 01:06:26 +03:00
/**
2015-08-19 19:46:42 +03:00
* device_get_phy_mode - Get phy mode for given device
2015-08-13 01:06:26 +03:00
* @ dev : Pointer to the given device
*
* The function gets phy interface string from property ' phy - mode ' or
* ' phy - connection - type ' , and return its index in phy_modes table , or errno in
* error case .
*/
int device_get_phy_mode ( struct device * dev )
{
const char * pm ;
int err , i ;
err = device_property_read_string ( dev , " phy-mode " , & pm ) ;
if ( err < 0 )
err = device_property_read_string ( dev ,
" phy-connection-type " , & pm ) ;
if ( err < 0 )
return err ;
for ( i = 0 ; i < PHY_INTERFACE_MODE_MAX ; i + + )
if ( ! strcasecmp ( pm , phy_modes ( i ) ) )
return i ;
return - ENODEV ;
}
EXPORT_SYMBOL_GPL ( device_get_phy_mode ) ;
static void * device_get_mac_addr ( struct device * dev ,
const char * name , char * addr ,
int alen )
{
int ret = device_property_read_u8_array ( dev , name , addr , alen ) ;
2015-08-19 19:46:42 +03:00
if ( ret = = 0 & & alen = = ETH_ALEN & & is_valid_ether_addr ( addr ) )
2015-08-13 01:06:26 +03:00
return addr ;
return NULL ;
}
/**
2015-08-19 19:46:42 +03:00
* device_get_mac_address - Get the MAC for a given device
* @ dev : Pointer to the device
* @ addr : Address of buffer to store the MAC in
* @ alen : Length of the buffer pointed to by addr , should be ETH_ALEN
*
* Search the firmware node for the best MAC address to use . ' mac - address ' is
2015-08-13 01:06:26 +03:00
* checked first , because that is supposed to contain to " most recent " MAC
* address . If that isn ' t set , then ' local - mac - address ' is checked next ,
* because that is the default address . If that isn ' t set , then the obsolete
* ' address ' is checked , just in case we ' re using an old device tree .
*
* Note that the ' address ' property is supposed to contain a virtual address of
* the register set , but some DTS files have redefined that property to be the
* MAC address .
*
* All - zero MAC addresses are rejected , because those could be properties that
2015-08-19 19:46:42 +03:00
* exist in the firmware tables , but were not updated by the firmware . For
* example , the DTS could define ' mac - address ' and ' local - mac - address ' , with
* zero MAC addresses . Some older U - Boots only initialized ' local - mac - address ' .
* In this case , the real MAC is in ' local - mac - address ' , and ' mac - address '
* exists but is all zeros .
2015-08-13 01:06:26 +03:00
*/
void * device_get_mac_address ( struct device * dev , char * addr , int alen )
{
2015-09-04 01:59:50 +03:00
char * res ;
2015-08-13 01:06:26 +03:00
2015-09-04 01:59:50 +03:00
res = device_get_mac_addr ( dev , " mac-address " , addr , alen ) ;
if ( res )
return res ;
res = device_get_mac_addr ( dev , " local-mac-address " , addr , alen ) ;
if ( res )
return res ;
2015-08-13 01:06:26 +03:00
return device_get_mac_addr ( dev , " address " , addr , alen ) ;
}
EXPORT_SYMBOL ( device_get_mac_address ) ;