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>
2017-03-28 10:52:21 +03:00
# include <linux/of_graph.h>
2018-01-18 15:31:40 +03:00
# include <linux/of_irq.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
2016-03-29 14:52:23 +03:00
struct property_set {
2017-10-09 16:28:37 +03:00
struct device * dev ;
2016-03-29 14:52:23 +03:00
struct fwnode_handle fwnode ;
2017-02-03 04:41:25 +03:00
const struct property_entry * properties ;
2016-03-29 14:52:23 +03:00
} ;
2017-07-21 14:39:31 +03:00
static const struct fwnode_operations pset_fwnode_ops ;
2017-07-21 14:39:35 +03:00
static inline bool is_pset_node ( const struct fwnode_handle * fwnode )
2015-04-03 17:05:11 +03:00
{
2017-07-21 14:39:31 +03:00
return ! IS_ERR_OR_NULL ( fwnode ) & & fwnode - > ops = = & pset_fwnode_ops ;
2015-04-03 17:05:11 +03:00
}
2017-07-21 14:39:35 +03:00
# define to_pset_node(__fwnode) \
( { \
typeof ( __fwnode ) __to_pset_node_fwnode = __fwnode ; \
\
is_pset_node ( __to_pset_node_fwnode ) ? \
container_of ( __to_pset_node_fwnode , \
struct property_set , fwnode ) : \
NULL ; \
} )
static const struct property_entry *
pset_prop_get ( const struct property_set * pset , const char * name )
2015-04-03 17:05:11 +03:00
{
2017-02-03 04:41:25 +03:00
const struct property_entry * prop ;
2015-04-03 17:05:11 +03:00
if ( ! pset | | ! pset - > properties )
return NULL ;
for ( prop = pset - > properties ; prop - > name ; prop + + )
if ( ! strcmp ( name , prop - > name ) )
return prop ;
return NULL ;
}
2017-07-21 14:39:35 +03:00
static const void * pset_prop_find ( const struct property_set * pset ,
2017-02-03 04:41:25 +03:00
const char * propname , size_t length )
2015-04-03 17:05:11 +03:00
{
2017-02-03 04:41:25 +03:00
const struct property_entry * prop ;
const 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 ;
}
2017-07-21 14:39:35 +03:00
static int pset_prop_read_u8_array ( const struct property_set * pset ,
2015-11-30 18:11:31 +03:00
const char * propname ,
u8 * values , size_t nval )
{
2017-02-03 04:41:25 +03:00
const void * pointer ;
2015-11-30 18:11:31 +03:00
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 ;
}
2017-07-21 14:39:35 +03:00
static int pset_prop_read_u16_array ( const struct property_set * pset ,
2015-11-30 18:11:31 +03:00
const char * propname ,
u16 * values , size_t nval )
{
2017-02-03 04:41:25 +03:00
const void * pointer ;
2015-11-30 18:11:31 +03:00
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 ;
}
2017-07-21 14:39:35 +03:00
static int pset_prop_read_u32_array ( const struct property_set * pset ,
2015-11-30 18:11:31 +03:00
const char * propname ,
u32 * values , size_t nval )
{
2017-02-03 04:41:25 +03:00
const void * pointer ;
2015-11-30 18:11:31 +03:00
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 ;
}
2017-07-21 14:39:35 +03:00
static int pset_prop_read_u64_array ( const struct property_set * pset ,
2015-11-30 18:11:31 +03:00
const char * propname ,
u64 * values , size_t nval )
{
2017-02-03 04:41:25 +03:00
const void * pointer ;
2015-11-30 18:11:31 +03:00
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 ;
}
2017-07-21 14:39:35 +03:00
static int pset_prop_count_elems_of_size ( const struct property_set * pset ,
2015-11-30 18:11:31 +03:00
const char * propname , size_t length )
{
2017-02-03 04:41:25 +03:00
const struct property_entry * prop ;
2015-11-30 18:11:31 +03:00
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 ;
}
2017-07-21 14:39:35 +03:00
static int pset_prop_read_string_array ( const struct property_set * pset ,
2015-11-30 18:11:31 +03:00
const char * propname ,
const char * * strings , size_t nval )
{
2017-03-28 15:22:18 +03:00
const struct property_entry * prop ;
2017-02-03 04:41:25 +03:00
const void * pointer ;
2017-03-28 15:22:18 +03:00
size_t array_len , length ;
/* Find out the array length. */
prop = pset_prop_get ( pset , propname ) ;
if ( ! prop )
return - EINVAL ;
if ( ! prop - > is_array )
/* The array length for a non-array string property is 1. */
array_len = 1 ;
else
/* Find the length of an array. */
array_len = pset_prop_count_elems_of_size ( pset , propname ,
sizeof ( const char * ) ) ;
/* Return how many there are if strings is NULL. */
if ( ! strings )
return array_len ;
array_len = min ( nval , array_len ) ;
length = array_len * sizeof ( * strings ) ;
2015-11-30 18:11:31 +03:00
pointer = pset_prop_find ( pset , propname , length ) ;
if ( IS_ERR ( pointer ) )
return PTR_ERR ( pointer ) ;
memcpy ( strings , pointer , length ) ;
2017-03-28 15:22:18 +03:00
2017-03-28 15:22:19 +03:00
return array_len ;
2015-04-03 17:05:11 +03:00
}
2014-11-04 03:28:56 +03:00
2017-03-28 10:52:24 +03:00
struct fwnode_handle * dev_fwnode ( struct device * dev )
2015-03-24 02:24:16 +03:00
{
return IS_ENABLED ( CONFIG_OF ) & & dev - > of_node ?
& dev - > of_node - > fwnode : dev - > fwnode ;
}
2017-03-28 10:52:24 +03:00
EXPORT_SYMBOL_GPL ( dev_fwnode ) ;
2014-11-04 03:28:56 +03:00
2017-07-21 14:39:36 +03:00
static bool pset_fwnode_property_present ( const struct fwnode_handle * fwnode ,
2017-06-06 12:37:37 +03:00
const char * propname )
{
return ! ! pset_prop_get ( to_pset_node ( fwnode ) , propname ) ;
}
2017-07-21 14:39:36 +03:00
static int pset_fwnode_read_int_array ( const struct fwnode_handle * fwnode ,
2017-06-06 12:37:37 +03:00
const char * propname ,
unsigned int elem_size , void * val ,
size_t nval )
{
2017-07-21 14:39:36 +03:00
const struct property_set * node = to_pset_node ( fwnode ) ;
2017-06-06 12:37:37 +03:00
if ( ! val )
return pset_prop_count_elems_of_size ( node , propname , elem_size ) ;
switch ( elem_size ) {
case sizeof ( u8 ) :
return pset_prop_read_u8_array ( node , propname , val , nval ) ;
case sizeof ( u16 ) :
return pset_prop_read_u16_array ( node , propname , val , nval ) ;
case sizeof ( u32 ) :
return pset_prop_read_u32_array ( node , propname , val , nval ) ;
case sizeof ( u64 ) :
return pset_prop_read_u64_array ( node , propname , val , nval ) ;
}
return - ENXIO ;
}
2017-07-21 14:39:36 +03:00
static int
pset_fwnode_property_read_string_array ( const struct fwnode_handle * fwnode ,
const char * propname ,
const char * * val , size_t nval )
2017-06-06 12:37:37 +03:00
{
return pset_prop_read_string_array ( to_pset_node ( fwnode ) , propname ,
val , nval ) ;
}
static const struct fwnode_operations pset_fwnode_ops = {
. property_present = pset_fwnode_property_present ,
. property_read_int_array = pset_fwnode_read_int_array ,
. property_read_string_array = pset_fwnode_property_read_string_array ,
} ;
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
/**
* 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
*/
2017-07-21 14:39:36 +03:00
bool fwnode_property_present ( const struct fwnode_handle * fwnode ,
const char * propname )
2015-11-30 18:11:36 +03:00
{
bool ret ;
2017-07-11 18:20:20 +03:00
ret = fwnode_call_bool_op ( fwnode , property_present , propname ) ;
2016-03-10 14:03:18 +03:00
if ( ret = = false & & ! IS_ERR_OR_NULL ( fwnode ) & &
! IS_ERR_OR_NULL ( fwnode - > secondary ) )
2017-07-11 18:20:20 +03:00
ret = fwnode_call_bool_op ( fwnode - > secondary , property_present ,
2017-06-06 12:37:37 +03:00
propname ) ;
2015-11-30 18:11:36 +03:00
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 .
*
2017-03-28 15:22:19 +03:00
* Return : number of values read on success if @ val is non - NULL ,
* number of values available on success if @ val is NULL ,
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 ) ;
2017-07-21 14:39:36 +03:00
static int fwnode_property_read_int_array ( const struct fwnode_handle * fwnode ,
2017-06-06 12:37:37 +03:00
const char * propname ,
unsigned int elem_size , void * val ,
size_t nval )
{
int ret ;
ret = fwnode_call_int_op ( fwnode , property_read_int_array , propname ,
elem_size , val , nval ) ;
if ( ret = = - EINVAL & & ! IS_ERR_OR_NULL ( fwnode ) & &
! IS_ERR_OR_NULL ( fwnode - > secondary ) )
ret = fwnode_call_int_op (
fwnode - > secondary , property_read_int_array , propname ,
elem_size , val , nval ) ;
return ret ;
}
2015-11-30 18:11:36 +03:00
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 .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_read_u8_array ( const struct fwnode_handle * fwnode ,
2014-11-04 16:03:59 +03:00
const char * propname , u8 * val , size_t nval )
{
2017-06-06 12:37:37 +03:00
return fwnode_property_read_int_array ( fwnode , propname , sizeof ( u8 ) ,
val , nval ) ;
2014-11-04 16:03:59 +03:00
}
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 .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_read_u16_array ( const struct fwnode_handle * fwnode ,
2014-11-04 16:03:59 +03:00
const char * propname , u16 * val , size_t nval )
{
2017-06-06 12:37:37 +03:00
return fwnode_property_read_int_array ( fwnode , propname , sizeof ( u16 ) ,
val , nval ) ;
2014-11-04 16:03:59 +03:00
}
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 .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_read_u32_array ( const struct fwnode_handle * fwnode ,
2014-11-04 16:03:59 +03:00
const char * propname , u32 * val , size_t nval )
{
2017-06-06 12:37:37 +03:00
return fwnode_property_read_int_array ( fwnode , propname , sizeof ( u32 ) ,
val , nval ) ;
2014-11-04 16:03:59 +03:00
}
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 .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_read_u64_array ( const struct fwnode_handle * fwnode ,
2014-11-04 16:03:59 +03:00
const char * propname , u64 * val , size_t nval )
{
2017-06-06 12:37:37 +03:00
return fwnode_property_read_int_array ( fwnode , propname , sizeof ( u64 ) ,
val , nval ) ;
2014-11-04 16:03:59 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_property_read_u64_array ) ;
/**
* 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 .
*
2017-03-28 15:22:19 +03:00
* Return : number of values read on success if @ val is non - NULL ,
* number of values available on success if @ val is NULL ,
2014-11-04 16:03:59 +03:00
* % - EINVAL if given arguments are not valid ,
* % - ENODATA if the property does not have a value ,
2017-03-28 15:22:17 +03:00
* % - EPROTO or % - EILSEQ if the property is not an array of strings ,
2014-11-04 16:03:59 +03:00
* % - EOVERFLOW if the size of the property is not as expected ,
* % - ENXIO if no suitable firmware interface is present .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_read_string_array ( const struct fwnode_handle * fwnode ,
2014-11-04 16:03:59 +03:00
const char * propname , const char * * val ,
size_t nval )
{
2015-11-30 18:11:36 +03:00
int ret ;
2017-06-06 12:37:37 +03:00
ret = fwnode_call_int_op ( fwnode , property_read_string_array , propname ,
val , nval ) ;
2016-03-10 14:03:18 +03:00
if ( ret = = - EINVAL & & ! IS_ERR_OR_NULL ( fwnode ) & &
! IS_ERR_OR_NULL ( fwnode - > secondary ) )
2017-06-06 12:37:37 +03:00
ret = fwnode_call_int_op ( fwnode - > secondary ,
property_read_string_array , propname ,
val , nval ) ;
2015-11-30 18:11:36 +03:00
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 .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_read_string ( const struct fwnode_handle * fwnode ,
2014-11-04 16:03:59 +03:00
const char * propname , const char * * val )
{
2017-03-28 15:26:22 +03:00
int ret = fwnode_property_read_string_array ( fwnode , propname , val , 1 ) ;
2015-11-30 18:11:36 +03:00
2017-03-28 15:22:19 +03:00
return ret < 0 ? ret : 0 ;
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 .
*/
2017-07-21 14:39:36 +03:00
int fwnode_property_match_string ( const struct fwnode_handle * fwnode ,
2015-09-14 17:37:35 +03:00
const char * propname , const char * string )
{
const char * * values ;
2016-03-18 00:22:17 +03:00
int nval , ret ;
2015-09-14 17:37:35 +03:00
nval = fwnode_property_read_string_array ( fwnode , propname , NULL , 0 ) ;
if ( nval < 0 )
return nval ;
2015-12-29 14:07:50 +03:00
if ( nval = = 0 )
return - ENODATA ;
2015-09-14 17:37:35 +03:00
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 ;
2016-03-18 00:22:17 +03:00
ret = match_string ( values , nval , string ) ;
if ( ret < 0 )
ret = - ENODATA ;
2015-09-14 17:37:35 +03:00
out :
kfree ( values ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_match_string ) ;
2017-07-21 15:11:49 +03:00
/**
* fwnode_property_get_reference_args ( ) - Find a reference with arguments
* @ fwnode : Firmware node where to look for the reference
* @ prop : The name of the property
* @ nargs_prop : The name of the property telling the number of
* arguments in the referred node . NULL if @ nargs is known ,
* otherwise @ nargs is ignored . Only relevant on OF .
* @ nargs : Number of arguments . Ignored if @ nargs_prop is non - NULL .
* @ index : Index of the reference , from zero onwards .
* @ args : Result structure with reference and integer arguments .
*
* Obtain a reference based on a named property in an fwnode , with
* integer arguments .
*
* Caller is responsible to call fwnode_handle_put ( ) on the returned
* args - > fwnode pointer .
*
2017-09-26 12:08:27 +03:00
* Returns : % 0 on success
* % - ENOENT when the index is out of bounds , the index has an empty
* reference or the property was not found
* % - EINVAL on parse error
2017-07-21 15:11:49 +03:00
*/
int fwnode_property_get_reference_args ( const struct fwnode_handle * fwnode ,
const char * prop , const char * nargs_prop ,
unsigned int nargs , unsigned int index ,
struct fwnode_reference_args * args )
{
return fwnode_call_int_op ( fwnode , get_reference_args , prop , nargs_prop ,
nargs , index , args ) ;
}
EXPORT_SYMBOL_GPL ( fwnode_property_get_reference_args ) ;
2017-02-03 04:41:27 +03:00
static int property_copy_string_array ( struct property_entry * dst ,
const struct property_entry * src )
2015-11-30 18:11:37 +03:00
{
2017-02-03 04:41:27 +03:00
char * * d ;
size_t nval = src - > length / sizeof ( * d ) ;
int i ;
2015-11-30 18:11:37 +03:00
2017-02-03 04:41:27 +03:00
d = kcalloc ( nval , sizeof ( * d ) , GFP_KERNEL ) ;
if ( ! d )
return - ENOMEM ;
2015-11-30 18:11:37 +03:00
2017-02-03 04:41:27 +03:00
for ( i = 0 ; i < nval ; i + + ) {
d [ i ] = kstrdup ( src - > pointer . str [ i ] , GFP_KERNEL ) ;
if ( ! d [ i ] & & src - > pointer . str [ i ] ) {
while ( - - i > = 0 )
kfree ( d [ i ] ) ;
kfree ( d ) ;
return - ENOMEM ;
2015-11-30 18:11:37 +03:00
}
}
2017-02-03 04:41:27 +03:00
dst - > pointer . raw_data = d ;
return 0 ;
2015-11-30 18:11:37 +03:00
}
2017-02-03 04:41:27 +03:00
static int property_entry_copy_data ( struct property_entry * dst ,
const struct property_entry * src )
2015-11-30 18:11:37 +03:00
{
2017-02-03 04:41:27 +03:00
int error ;
2015-11-30 18:11:37 +03:00
dst - > name = kstrdup ( src - > name , GFP_KERNEL ) ;
if ( ! dst - > name )
return - ENOMEM ;
if ( src - > is_array ) {
2017-02-03 04:41:27 +03:00
if ( ! src - > length ) {
error = - ENODATA ;
goto out_free_name ;
}
2015-12-29 14:07:50 +03:00
2015-11-30 18:11:37 +03:00
if ( src - > is_string ) {
2017-02-03 04:41:27 +03:00
error = property_copy_string_array ( dst , src ) ;
if ( error )
goto out_free_name ;
2015-11-30 18:11:37 +03:00
} else {
dst - > pointer . raw_data = kmemdup ( src - > pointer . raw_data ,
src - > length , GFP_KERNEL ) ;
2017-02-03 04:41:27 +03:00
if ( ! dst - > pointer . raw_data ) {
error = - ENOMEM ;
goto out_free_name ;
}
2015-11-30 18:11:37 +03:00
}
} else if ( src - > is_string ) {
dst - > value . str = kstrdup ( src - > value . str , GFP_KERNEL ) ;
2017-02-03 04:41:27 +03:00
if ( ! dst - > value . str & & src - > value . str ) {
error = - ENOMEM ;
goto out_free_name ;
}
2015-11-30 18:11:37 +03:00
} else {
dst - > value . raw_data = src - > value . raw_data ;
}
dst - > length = src - > length ;
dst - > is_array = src - > is_array ;
dst - > is_string = src - > is_string ;
return 0 ;
2017-02-03 04:41:27 +03:00
out_free_name :
kfree ( dst - > name ) ;
return error ;
}
static void property_entry_free_data ( const struct property_entry * p )
{
size_t i , nval ;
if ( p - > is_array ) {
if ( p - > is_string & & p - > pointer . str ) {
nval = p - > length / sizeof ( const char * ) ;
for ( i = 0 ; i < nval ; i + + )
kfree ( p - > pointer . str [ i ] ) ;
}
kfree ( p - > pointer . raw_data ) ;
} else if ( p - > is_string ) {
kfree ( p - > value . str ) ;
}
kfree ( p - > name ) ;
}
/**
* property_entries_dup - duplicate array of properties
* @ properties : array of properties to copy
*
* This function creates a deep copy of the given NULL - terminated array
* of property entries .
*/
struct property_entry *
property_entries_dup ( const struct property_entry * properties )
{
struct property_entry * p ;
int i , n = 0 ;
while ( properties [ n ] . name )
n + + ;
p = kcalloc ( n + 1 , sizeof ( * p ) , GFP_KERNEL ) ;
if ( ! p )
return ERR_PTR ( - ENOMEM ) ;
for ( i = 0 ; i < n ; i + + ) {
int ret = property_entry_copy_data ( & p [ i ] , & properties [ i ] ) ;
if ( ret ) {
while ( - - i > = 0 )
property_entry_free_data ( & p [ i ] ) ;
kfree ( p ) ;
return ERR_PTR ( ret ) ;
}
}
return p ;
}
EXPORT_SYMBOL_GPL ( property_entries_dup ) ;
/**
* property_entries_free - free previously allocated array of properties
* @ properties : array of properties to destroy
*
* This function frees given NULL - terminated array of property entries ,
* along with their data .
*/
void property_entries_free ( const struct property_entry * properties )
{
const struct property_entry * p ;
for ( p = properties ; p - > name ; p + + )
property_entry_free_data ( p ) ;
kfree ( properties ) ;
}
EXPORT_SYMBOL_GPL ( property_entries_free ) ;
/**
* pset_free_set - releases memory allocated for copied property set
* @ pset : Property set to release
*
* Function takes previously copied property set and releases all the
* memory allocated to it .
*/
static void pset_free_set ( struct property_set * pset )
{
if ( ! pset )
return ;
property_entries_free ( pset - > properties ) ;
kfree ( pset ) ;
2015-11-30 18:11:37 +03:00
}
/**
* pset_copy_set - copies property set
* @ pset : Property set to copy
*
* This function takes a deep copy of the given property set and returns
* pointer to the copy . Call device_free_property_set ( ) to free resources
* allocated in this function .
*
* Return : Pointer to the new property set or error pointer .
*/
static struct property_set * pset_copy_set ( const struct property_set * pset )
{
2017-02-03 04:41:27 +03:00
struct property_entry * properties ;
2015-11-30 18:11:37 +03:00
struct property_set * p ;
p = kzalloc ( sizeof ( * p ) , GFP_KERNEL ) ;
if ( ! p )
return ERR_PTR ( - ENOMEM ) ;
2017-02-03 04:41:27 +03:00
properties = property_entries_dup ( pset - > properties ) ;
if ( IS_ERR ( properties ) ) {
2015-11-30 18:11:37 +03:00
kfree ( p ) ;
2017-02-03 04:41:27 +03:00
return ERR_CAST ( properties ) ;
2015-11-30 18:11:37 +03:00
}
2017-02-03 04:41:27 +03:00
p - > properties = properties ;
2015-11-30 18:11:37 +03:00
return p ;
}
/**
2016-03-29 14:52:23 +03:00
* device_remove_properties - Remove properties from a device object .
2015-11-30 18:11:37 +03:00
* @ dev : Device whose properties to remove .
*
* The function removes properties previously associated to the device
2016-03-29 14:52:23 +03:00
* secondary firmware node with device_add_properties ( ) . Memory allocated
2015-11-30 18:11:37 +03:00
* to the properties will also be released .
*/
2016-03-29 14:52:23 +03:00
void device_remove_properties ( struct device * dev )
2015-11-30 18:11:37 +03:00
{
struct fwnode_handle * fwnode ;
2017-10-09 16:28:37 +03:00
struct property_set * pset ;
2015-11-30 18:11:37 +03:00
fwnode = dev_fwnode ( dev ) ;
if ( ! fwnode )
return ;
/*
* Pick either primary or secondary node depending which one holds
* the pset . If there is no real firmware node ( ACPI / DT ) primary
* will hold the pset .
*/
2017-10-09 16:28:37 +03:00
pset = to_pset_node ( fwnode ) ;
if ( pset ) {
2016-03-10 14:03:18 +03:00
set_primary_fwnode ( dev , NULL ) ;
} else {
2017-10-09 16:28:37 +03:00
pset = to_pset_node ( fwnode - > secondary ) ;
if ( pset & & dev = = pset - > dev )
2016-03-10 14:03:18 +03:00
set_secondary_fwnode ( dev , NULL ) ;
}
2017-10-09 16:28:37 +03:00
if ( pset & & dev = = pset - > dev )
pset_free_set ( pset ) ;
2015-11-30 18:11:37 +03:00
}
2016-03-29 14:52:23 +03:00
EXPORT_SYMBOL_GPL ( device_remove_properties ) ;
2015-11-30 18:11:37 +03:00
/**
2016-03-29 14:52:23 +03:00
* device_add_properties - Add a collection of properties to a device object .
2015-11-30 18:11:37 +03:00
* @ dev : Device to add properties to .
2016-03-29 14:52:23 +03:00
* @ properties : Collection of properties to add .
2015-11-30 18:11:37 +03:00
*
2016-03-29 14:52:23 +03:00
* Associate a collection of device properties represented by @ properties with
* @ dev as its secondary firmware node . The function takes a copy of
* @ properties .
2015-11-30 18:11:37 +03:00
*/
2017-02-03 04:41:25 +03:00
int device_add_properties ( struct device * dev ,
const struct property_entry * properties )
2015-11-30 18:11:37 +03:00
{
2016-03-29 14:52:23 +03:00
struct property_set * p , pset ;
2015-11-30 18:11:37 +03:00
2016-03-29 14:52:23 +03:00
if ( ! properties )
2015-11-30 18:11:37 +03:00
return - EINVAL ;
2016-03-29 14:52:23 +03:00
pset . properties = properties ;
p = pset_copy_set ( & pset ) ;
2015-11-30 18:11:37 +03:00
if ( IS_ERR ( p ) )
return PTR_ERR ( p ) ;
2017-06-06 12:37:37 +03:00
p - > fwnode . ops = & pset_fwnode_ops ;
2015-11-30 18:11:37 +03:00
set_secondary_fwnode ( dev , & p - > fwnode ) ;
2017-10-09 16:28:37 +03:00
p - > dev = dev ;
2015-11-30 18:11:37 +03:00
return 0 ;
}
2016-03-29 14:52:23 +03:00
EXPORT_SYMBOL_GPL ( device_add_properties ) ;
2015-11-30 18:11:37 +03:00
2017-03-28 10:52:26 +03:00
/**
* fwnode_get_next_parent - Iterate to the node ' s parent
* @ fwnode : Firmware whose parent is retrieved
*
* This is like fwnode_get_parent ( ) except that it drops the refcount
* on the passed node , making it suitable for iterating through a
* node ' s parents .
*
* Returns a node pointer with refcount incremented , use
* fwnode_handle_node ( ) on it when done .
*/
struct fwnode_handle * fwnode_get_next_parent ( struct fwnode_handle * fwnode )
{
struct fwnode_handle * parent = fwnode_get_parent ( fwnode ) ;
fwnode_handle_put ( fwnode ) ;
return parent ;
}
EXPORT_SYMBOL_GPL ( fwnode_get_next_parent ) ;
2017-03-28 10:52:17 +03:00
/**
* fwnode_get_parent - Return parent firwmare node
* @ fwnode : Firmware whose parent is retrieved
*
* Return parent firmware node of the given node if possible or % NULL if no
* parent was available .
*/
2017-07-21 14:39:36 +03:00
struct fwnode_handle * fwnode_get_parent ( const struct fwnode_handle * fwnode )
2017-03-28 10:52:17 +03:00
{
2017-06-06 12:37:37 +03:00
return fwnode_call_ptr_op ( fwnode , get_parent ) ;
2017-03-28 10:52:17 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_get_parent ) ;
2014-11-04 16:03:59 +03:00
/**
2017-03-28 10:52:18 +03:00
* fwnode_get_next_child_node - Return the next child node handle for a node
* @ fwnode : Firmware node to find the next child node for .
* @ child : Handle to one of the node ' s child nodes or a % NULL handle .
2014-11-04 16:03:59 +03:00
*/
2017-07-21 14:39:36 +03:00
struct fwnode_handle *
fwnode_get_next_child_node ( const struct fwnode_handle * fwnode ,
struct fwnode_handle * child )
2014-11-04 16:03:59 +03:00
{
2017-06-06 12:37:37 +03:00
return fwnode_call_ptr_op ( fwnode , get_next_child_node , child ) ;
2014-11-04 16:03:59 +03:00
}
2017-03-28 10:52:18 +03:00
EXPORT_SYMBOL_GPL ( fwnode_get_next_child_node ) ;
/**
* 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 )
{
struct acpi_device * adev = ACPI_COMPANION ( dev ) ;
struct fwnode_handle * fwnode = NULL ;
if ( dev - > of_node )
fwnode = & dev - > of_node - > fwnode ;
else if ( adev )
fwnode = acpi_fwnode_handle ( adev ) ;
return fwnode_get_next_child_node ( fwnode , child ) ;
}
2014-11-04 16:03:59 +03:00
EXPORT_SYMBOL_GPL ( device_get_next_child_node ) ;
2016-06-21 20:50:20 +03:00
/**
2017-03-28 10:52:19 +03:00
* fwnode_get_named_child_node - Return first matching named child node handle
* @ fwnode : Firmware node to find the named child node for .
2016-06-21 20:50:20 +03:00
* @ childname : String to match child node name against .
*/
2017-07-21 14:39:36 +03:00
struct fwnode_handle *
fwnode_get_named_child_node ( const struct fwnode_handle * fwnode ,
const char * childname )
2016-06-21 20:50:20 +03:00
{
2017-06-06 12:37:37 +03:00
return fwnode_call_ptr_op ( fwnode , get_named_child_node , childname ) ;
2016-06-21 20:50:20 +03:00
}
2017-03-28 10:52:19 +03:00
EXPORT_SYMBOL_GPL ( fwnode_get_named_child_node ) ;
/**
* device_get_named_child_node - Return first matching named child node handle
* @ dev : Device to find the named child node for .
* @ childname : String to match child node name against .
*/
struct fwnode_handle * device_get_named_child_node ( struct device * dev ,
const char * childname )
{
return fwnode_get_named_child_node ( dev_fwnode ( dev ) , childname ) ;
}
2016-06-21 20:50:20 +03:00
EXPORT_SYMBOL_GPL ( device_get_named_child_node ) ;
2017-03-28 10:52:22 +03:00
/**
* fwnode_handle_get - Obtain a reference to a device node
* @ fwnode : Pointer to the device node to obtain the reference to .
2017-09-19 12:39:11 +03:00
*
* Returns the fwnode handle .
2017-03-28 10:52:22 +03:00
*/
2017-09-19 12:39:11 +03:00
struct fwnode_handle * fwnode_handle_get ( struct fwnode_handle * fwnode )
2017-03-28 10:52:22 +03:00
{
2017-09-19 12:39:11 +03:00
if ( ! fwnode_has_op ( fwnode , get ) )
return fwnode ;
return fwnode_call_ptr_op ( fwnode , get ) ;
2017-03-28 10:52:22 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_handle_get ) ;
2014-11-04 16:03:59 +03:00
/**
* 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 )
{
2017-06-06 12:37:37 +03:00
fwnode_call_void_op ( fwnode , put ) ;
2014-11-04 16:03:59 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_handle_put ) ;
2017-06-06 12:37:39 +03:00
/**
* fwnode_device_is_available - check if a device is available for use
* @ fwnode : Pointer to the fwnode of the device .
*/
2017-07-21 14:39:36 +03:00
bool fwnode_device_is_available ( const struct fwnode_handle * fwnode )
2017-06-06 12:37:39 +03:00
{
2017-07-11 18:20:20 +03:00
return fwnode_call_bool_op ( fwnode , device_is_available ) ;
2017-06-06 12:37:39 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_device_is_available ) ;
2014-11-04 16:03:59 +03:00
/**
* 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
/**
2018-01-18 15:31:39 +03:00
* fwnode_get_phy_mode - Get phy mode for given firmware node
* @ fwnode : Pointer to the given node
2015-08-13 01:06:26 +03:00
*
* 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 .
*/
2018-01-18 15:31:39 +03:00
int fwnode_get_phy_mode ( struct fwnode_handle * fwnode )
2015-08-13 01:06:26 +03:00
{
const char * pm ;
int err , i ;
2018-01-18 15:31:39 +03:00
err = fwnode_property_read_string ( fwnode , " phy-mode " , & pm ) ;
2015-08-13 01:06:26 +03:00
if ( err < 0 )
2018-01-18 15:31:39 +03:00
err = fwnode_property_read_string ( fwnode ,
2015-08-13 01:06:26 +03:00
" 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 ;
}
2018-01-18 15:31:39 +03:00
EXPORT_SYMBOL_GPL ( fwnode_get_phy_mode ) ;
/**
* device_get_phy_mode - Get phy mode for given device
* @ 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 )
{
return fwnode_get_phy_mode ( dev_fwnode ( dev ) ) ;
}
2015-08-13 01:06:26 +03:00
EXPORT_SYMBOL_GPL ( device_get_phy_mode ) ;
2018-01-18 15:31:38 +03:00
static void * fwnode_get_mac_addr ( struct fwnode_handle * fwnode ,
2015-08-13 01:06:26 +03:00
const char * name , char * addr ,
int alen )
{
2018-01-18 15:31:38 +03:00
int ret = fwnode_property_read_u8_array ( fwnode , name , addr , alen ) ;
2015-08-13 01:06:26 +03:00
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 ;
}
/**
2018-01-18 15:31:38 +03:00
* fwnode_get_mac_address - Get the MAC from the firmware node
* @ fwnode : Pointer to the firmware node
2015-08-19 19:46:42 +03:00
* @ 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
*/
2018-01-18 15:31:38 +03:00
void * fwnode_get_mac_address ( struct fwnode_handle * fwnode , char * addr , int alen )
2015-08-13 01:06:26 +03:00
{
2015-09-04 01:59:50 +03:00
char * res ;
2015-08-13 01:06:26 +03:00
2018-01-18 15:31:38 +03:00
res = fwnode_get_mac_addr ( fwnode , " mac-address " , addr , alen ) ;
2015-09-04 01:59:50 +03:00
if ( res )
return res ;
2018-01-18 15:31:38 +03:00
res = fwnode_get_mac_addr ( fwnode , " local-mac-address " , addr , alen ) ;
2015-09-04 01:59:50 +03:00
if ( res )
return res ;
2015-08-13 01:06:26 +03:00
2018-01-18 15:31:38 +03:00
return fwnode_get_mac_addr ( fwnode , " address " , addr , alen ) ;
}
EXPORT_SYMBOL ( fwnode_get_mac_address ) ;
/**
* 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
*/
void * device_get_mac_address ( struct device * dev , char * addr , int alen )
{
return fwnode_get_mac_address ( dev_fwnode ( dev ) , addr , alen ) ;
2015-08-13 01:06:26 +03:00
}
EXPORT_SYMBOL ( device_get_mac_address ) ;
2017-03-28 10:52:21 +03:00
2018-01-18 15:31:40 +03:00
/**
* fwnode_irq_get - Get IRQ directly from a fwnode
* @ fwnode : Pointer to the firmware node
* @ index : Zero - based index of the IRQ
*
* Returns Linux IRQ number on success . Other values are determined
* accordingly to acpi_ / of_ irq_get ( ) operation .
*/
int fwnode_irq_get ( struct fwnode_handle * fwnode , unsigned int index )
{
struct device_node * of_node = to_of_node ( fwnode ) ;
struct resource res ;
int ret ;
if ( IS_ENABLED ( CONFIG_OF ) & & of_node )
return of_irq_get ( of_node , index ) ;
ret = acpi_irq_get ( ACPI_HANDLE_FWNODE ( fwnode ) , index , & res ) ;
if ( ret )
return ret ;
return res . start ;
}
EXPORT_SYMBOL ( fwnode_irq_get ) ;
2017-03-28 10:52:21 +03:00
/**
* device_graph_get_next_endpoint - Get next endpoint firmware node
* @ fwnode : Pointer to the parent firmware node
* @ prev : Previous endpoint node or % NULL to get the first
*
* Returns an endpoint firmware node pointer or % NULL if no more endpoints
* are available .
*/
struct fwnode_handle *
2017-07-21 14:39:36 +03:00
fwnode_graph_get_next_endpoint ( const struct fwnode_handle * fwnode ,
2017-03-28 10:52:21 +03:00
struct fwnode_handle * prev )
{
2017-06-06 12:37:38 +03:00
return fwnode_call_ptr_op ( fwnode , graph_get_next_endpoint , prev ) ;
2017-03-28 10:52:21 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_next_endpoint ) ;
2017-06-06 12:37:41 +03:00
/**
* fwnode_graph_get_port_parent - Return the device fwnode of a port endpoint
* @ endpoint : Endpoint firmware node of the port
*
* Return : the firmware node of the device the @ endpoint belongs to .
*/
struct fwnode_handle *
2017-07-21 14:39:36 +03:00
fwnode_graph_get_port_parent ( const struct fwnode_handle * endpoint )
2017-06-06 12:37:41 +03:00
{
struct fwnode_handle * port , * parent ;
port = fwnode_get_parent ( endpoint ) ;
parent = fwnode_call_ptr_op ( port , graph_get_port_parent ) ;
fwnode_handle_put ( port ) ;
return parent ;
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_port_parent ) ;
2017-03-28 10:52:21 +03:00
/**
* fwnode_graph_get_remote_port_parent - Return fwnode of a remote device
* @ fwnode : Endpoint firmware node pointing to the remote endpoint
*
* Extracts firmware node of a remote device the @ fwnode points to .
*/
struct fwnode_handle *
2017-07-21 14:39:36 +03:00
fwnode_graph_get_remote_port_parent ( const struct fwnode_handle * fwnode )
2017-03-28 10:52:21 +03:00
{
2017-06-06 12:37:41 +03:00
struct fwnode_handle * endpoint , * parent ;
2017-03-28 10:52:21 +03:00
2017-06-06 12:37:41 +03:00
endpoint = fwnode_graph_get_remote_endpoint ( fwnode ) ;
parent = fwnode_graph_get_port_parent ( endpoint ) ;
2017-03-28 10:52:21 +03:00
2017-06-06 12:37:41 +03:00
fwnode_handle_put ( endpoint ) ;
2017-03-28 10:52:21 +03:00
return parent ;
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_remote_port_parent ) ;
/**
* fwnode_graph_get_remote_port - Return fwnode of a remote port
* @ fwnode : Endpoint firmware node pointing to the remote endpoint
*
* Extracts firmware node of a remote port the @ fwnode points to .
*/
2017-07-21 14:39:36 +03:00
struct fwnode_handle *
fwnode_graph_get_remote_port ( const struct fwnode_handle * fwnode )
2017-03-28 10:52:21 +03:00
{
2017-06-06 12:37:38 +03:00
return fwnode_get_next_parent ( fwnode_graph_get_remote_endpoint ( fwnode ) ) ;
2017-03-28 10:52:21 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_remote_port ) ;
/**
* fwnode_graph_get_remote_endpoint - Return fwnode of a remote endpoint
* @ fwnode : Endpoint firmware node pointing to the remote endpoint
*
* Extracts firmware node of a remote endpoint the @ fwnode points to .
*/
struct fwnode_handle *
2017-07-21 14:39:36 +03:00
fwnode_graph_get_remote_endpoint ( const struct fwnode_handle * fwnode )
2017-03-28 10:52:21 +03:00
{
2017-06-06 12:37:38 +03:00
return fwnode_call_ptr_op ( fwnode , graph_get_remote_endpoint ) ;
2017-03-28 10:52:21 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_remote_endpoint ) ;
2017-03-28 10:52:25 +03:00
2017-06-06 12:37:40 +03:00
/**
* fwnode_graph_get_remote_node - get remote parent node for given port / endpoint
* @ fwnode : pointer to parent fwnode_handle containing graph port / endpoint
* @ port_id : identifier of the parent port node
* @ endpoint_id : identifier of the endpoint node
*
* Return : Remote fwnode handle associated with remote endpoint node linked
* to @ node . Use fwnode_node_put ( ) on it when done .
*/
2017-07-21 14:39:36 +03:00
struct fwnode_handle *
fwnode_graph_get_remote_node ( const struct fwnode_handle * fwnode , u32 port_id ,
u32 endpoint_id )
2017-06-06 12:37:40 +03:00
{
struct fwnode_handle * endpoint = NULL ;
while ( ( endpoint = fwnode_graph_get_next_endpoint ( fwnode , endpoint ) ) ) {
struct fwnode_endpoint fwnode_ep ;
struct fwnode_handle * remote ;
int ret ;
ret = fwnode_graph_parse_endpoint ( endpoint , & fwnode_ep ) ;
if ( ret < 0 )
continue ;
if ( fwnode_ep . port ! = port_id | | fwnode_ep . id ! = endpoint_id )
continue ;
remote = fwnode_graph_get_remote_port_parent ( endpoint ) ;
if ( ! remote )
return NULL ;
return fwnode_device_is_available ( remote ) ? remote : NULL ;
}
return NULL ;
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_remote_node ) ;
2017-03-28 10:52:25 +03:00
/**
* fwnode_graph_parse_endpoint - parse common endpoint node properties
* @ fwnode : pointer to endpoint fwnode_handle
* @ endpoint : pointer to the fwnode endpoint data structure
*
* Parse @ fwnode representing a graph endpoint node and store the
* information in @ endpoint . The caller must hold a reference to
* @ fwnode .
*/
2017-07-21 14:39:36 +03:00
int fwnode_graph_parse_endpoint ( const struct fwnode_handle * fwnode ,
2017-03-28 10:52:25 +03:00
struct fwnode_endpoint * endpoint )
{
memset ( endpoint , 0 , sizeof ( * endpoint ) ) ;
2017-06-06 12:37:38 +03:00
return fwnode_call_int_op ( fwnode , graph_parse_endpoint , endpoint ) ;
2017-03-28 10:52:25 +03:00
}
EXPORT_SYMBOL ( fwnode_graph_parse_endpoint ) ;