2017-11-07 19:30:07 +03:00
// SPDX-License-Identifier: GPL-2.0
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 >
*/
# 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/phy.h>
2015-04-03 17:05:11 +03:00
2022-10-04 12:21:25 +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 ?
2021-05-10 12:56:12 +03:00
of_fwnode_handle ( dev - > of_node ) : dev - > fwnode ;
2015-03-24 02:24:16 +03:00
}
2022-10-04 12:21:25 +03:00
EXPORT_SYMBOL_GPL ( __dev_fwnode ) ;
const struct fwnode_handle * __dev_fwnode_const ( const struct device * dev )
{
return IS_ENABLED ( CONFIG_OF ) & & dev - > of_node ?
of_fwnode_handle ( dev - > of_node ) : dev - > fwnode ;
}
EXPORT_SYMBOL_GPL ( __dev_fwnode_const ) ;
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 ;
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
return false ;
2017-07-11 18:20:20 +03:00
ret = fwnode_call_bool_op ( fwnode , property_present , propname ) ;
2022-04-08 21:48:40 +03:00
if ( ret )
return ret ;
return fwnode_call_bool_op ( fwnode - > secondary , property_present , propname ) ;
2015-11-30 18:11:36 +03:00
}
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call device_property_count_u8 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call device_property_count_u16 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call device_property_count_u32 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call device_property_count_u64 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call device_property_string_array_count ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 ;
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
return - EINVAL ;
2017-06-06 12:37:37 +03:00
ret = fwnode_call_int_op ( fwnode , property_read_int_array , propname ,
elem_size , val , nval ) ;
2022-04-08 21:48:40 +03:00
if ( ret ! = - EINVAL )
return ret ;
2017-06-06 12:37:37 +03:00
2022-04-08 21:48:40 +03:00
return fwnode_call_int_op ( fwnode - > secondary , property_read_int_array , propname ,
elem_size , val , nval ) ;
2017-06-06 12:37:37 +03:00
}
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call fwnode_property_count_u8 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call fwnode_property_count_u16 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call fwnode_property_count_u32 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call fwnode_property_count_u64 ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 .
*
2022-05-02 12:51:01 +03:00
* It ' s recommended to call fwnode_property_string_array_count ( ) instead of calling
* this function with @ val equals % NULL and @ nval equals 0.
*
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 ;
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
return - EINVAL ;
2017-06-06 12:37:37 +03:00
ret = fwnode_call_int_op ( fwnode , property_read_string_array , propname ,
val , nval ) ;
2022-04-08 21:48:40 +03:00
if ( ret ! = - EINVAL )
return ret ;
return fwnode_call_int_op ( fwnode - > secondary , property_read_string_array , propname ,
val , nval ) ;
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 )
{
2021-11-29 02:24:55 +03:00
int ret ;
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
return - ENOENT ;
2021-11-29 02:24:55 +03:00
ret = fwnode_call_int_op ( fwnode , get_reference_args , prop , nargs_prop ,
nargs , index , args ) ;
2022-04-08 21:48:40 +03:00
if ( ret = = 0 )
return ret ;
2021-11-29 02:24:55 +03:00
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode - > secondary ) )
return ret ;
2021-11-29 02:24:55 +03:00
2022-04-08 21:48:40 +03:00
return fwnode_call_int_op ( fwnode - > secondary , get_reference_args , prop , nargs_prop ,
nargs , index , args ) ;
2017-07-21 15:11:49 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_property_get_reference_args ) ;
2019-05-31 17:15:39 +03:00
/**
* fwnode_find_reference - Find named reference to a fwnode_handle
* @ fwnode : Firmware node where to look for the reference
* @ name : The name of the reference
* @ index : Index of the reference
*
* @ index can be used when the named reference holds a table of references .
*
* Returns pointer to the reference fwnode , or ERR_PTR . Caller is responsible to
* call fwnode_handle_put ( ) on the returned fwnode pointer .
*/
struct fwnode_handle * fwnode_find_reference ( const struct fwnode_handle * fwnode ,
const char * name ,
unsigned int index )
{
struct fwnode_reference_args args ;
int ret ;
ret = fwnode_property_get_reference_args ( fwnode , name , NULL , 0 , index ,
& args ) ;
return ret ? ERR_PTR ( ret ) : args . fwnode ;
}
EXPORT_SYMBOL_GPL ( fwnode_find_reference ) ;
2019-10-03 15:32:12 +03:00
/**
* fwnode_get_name - Return the name of a node
* @ fwnode : The firmware node
*
* Returns a pointer to the node name .
*/
const char * fwnode_get_name ( const struct fwnode_handle * fwnode )
{
return fwnode_call_ptr_op ( fwnode , get_name ) ;
}
2020-03-02 16:53:51 +03:00
EXPORT_SYMBOL_GPL ( fwnode_get_name ) ;
2019-10-03 15:32:12 +03:00
2019-10-03 15:32:13 +03:00
/**
* fwnode_get_name_prefix - Return the prefix of node for printing purposes
* @ fwnode : The firmware node
*
* Returns the prefix of a node , intended to be printed right before the node .
* The prefix works also as a separator between the nodes .
*/
const char * fwnode_get_name_prefix ( const struct fwnode_handle * fwnode )
{
return fwnode_call_ptr_op ( fwnode , get_name_prefix ) ;
}
2019-10-03 15:32:10 +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 .
*/
struct fwnode_handle * fwnode_get_parent ( const struct fwnode_handle * fwnode )
{
return fwnode_call_ptr_op ( fwnode , get_parent ) ;
}
EXPORT_SYMBOL_GPL ( fwnode_get_parent ) ;
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 ) ;
2020-11-21 05:02:25 +03:00
/**
* fwnode_get_next_parent_dev - Find device of closest ancestor fwnode
* @ fwnode : firmware node
*
* Given a firmware node ( @ fwnode ) , this function finds its closest ancestor
* firmware node that has a corresponding struct device and returns that struct
* device .
*
* The caller of this function is expected to call put_device ( ) on the returned
* device when they are done .
*/
struct device * fwnode_get_next_parent_dev ( struct fwnode_handle * fwnode )
{
2022-04-08 21:48:41 +03:00
struct fwnode_handle * parent ;
2021-05-18 09:48:43 +03:00
struct device * dev ;
2020-11-21 05:02:25 +03:00
2022-04-08 21:48:41 +03:00
fwnode_for_each_parent_node ( fwnode , parent ) {
2022-04-30 02:43:47 +03:00
dev = get_dev_from_fwnode ( parent ) ;
2022-04-08 21:48:41 +03:00
if ( dev ) {
fwnode_handle_put ( parent ) ;
return dev ;
}
}
return NULL ;
2020-11-21 05:02:25 +03:00
}
2019-10-03 15:32:11 +03:00
/**
* fwnode_count_parents - Return the number of parents a node has
* @ fwnode : The node the parents of which are to be counted
*
* Returns the number of parents a node has .
*/
unsigned int fwnode_count_parents ( const struct fwnode_handle * fwnode )
{
2022-04-08 21:48:41 +03:00
struct fwnode_handle * parent ;
unsigned int count = 0 ;
2019-10-03 15:32:11 +03:00
2022-04-08 21:48:41 +03:00
fwnode_for_each_parent_node ( fwnode , parent )
count + + ;
2019-10-03 15:32:11 +03:00
return count ;
}
EXPORT_SYMBOL_GPL ( fwnode_count_parents ) ;
/**
* fwnode_get_nth_parent - Return an nth parent of a node
* @ fwnode : The node the parent of which is requested
* @ depth : Distance of the parent from the node
*
* Returns the nth parent of a node . If there is no parent at the requested
* @ depth , % NULL is returned . If @ depth is 0 , the functionality is equivalent to
* fwnode_handle_get ( ) . For @ depth = = 1 , it is fwnode_get_parent ( ) and so on .
*
* The caller is responsible for calling fwnode_handle_put ( ) for the returned
* node .
*/
struct fwnode_handle * fwnode_get_nth_parent ( struct fwnode_handle * fwnode ,
unsigned int depth )
{
2022-04-08 21:48:41 +03:00
struct fwnode_handle * parent ;
2019-10-03 15:32:11 +03:00
2022-04-08 21:48:41 +03:00
if ( depth = = 0 )
return fwnode_handle_get ( fwnode ) ;
2019-10-03 15:32:11 +03:00
2022-04-08 21:48:41 +03:00
fwnode_for_each_parent_node ( fwnode , parent ) {
if ( - - depth = = 0 )
return parent ;
}
return NULL ;
2019-10-03 15:32:11 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_get_nth_parent ) ;
2020-11-21 05:02:25 +03:00
/**
2022-04-08 21:48:42 +03:00
* fwnode_is_ancestor_of - Test if @ ancestor is ancestor of @ child
* @ ancestor : Firmware which is tested for being an ancestor
* @ child : Firmware which is tested for being the child
2020-11-21 05:02:25 +03:00
*
* A node is considered an ancestor of itself too .
*
2022-04-08 21:48:42 +03:00
* Returns true if @ ancestor is an ancestor of @ child . Otherwise , returns false .
2020-11-21 05:02:25 +03:00
*/
2022-04-08 21:48:42 +03:00
bool fwnode_is_ancestor_of ( struct fwnode_handle * ancestor , struct fwnode_handle * child )
2020-11-21 05:02:25 +03:00
{
2022-04-08 21:48:41 +03:00
struct fwnode_handle * parent ;
2022-04-08 21:48:42 +03:00
if ( IS_ERR_OR_NULL ( ancestor ) )
2020-11-21 05:02:25 +03:00
return false ;
2022-04-08 21:48:42 +03:00
if ( child = = ancestor )
2022-04-08 21:48:41 +03:00
return true ;
2022-04-08 21:48:42 +03:00
fwnode_for_each_parent_node ( child , parent ) {
if ( parent = = ancestor ) {
2022-04-08 21:48:41 +03:00
fwnode_handle_put ( parent ) ;
2020-11-21 05:02:25 +03:00
return true ;
}
2022-04-08 21:48:41 +03:00
}
2020-11-21 05:02:25 +03:00
return false ;
}
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 ) ;
2018-01-18 15:31:41 +03:00
/**
* fwnode_get_next_available_child_node - Return the next
* available 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 .
*/
struct fwnode_handle *
fwnode_get_next_available_child_node ( const struct fwnode_handle * fwnode ,
struct fwnode_handle * child )
{
struct fwnode_handle * next_child = child ;
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
2018-01-18 15:31:41 +03:00
return NULL ;
do {
next_child = fwnode_get_next_child_node ( fwnode , next_child ) ;
2021-05-18 09:48:43 +03:00
if ( ! next_child )
return NULL ;
} while ( ! fwnode_device_is_available ( next_child ) ) ;
2018-01-18 15:31:41 +03:00
return next_child ;
}
EXPORT_SYMBOL_GPL ( fwnode_get_next_available_child_node ) ;
2017-03-28 10:52:18 +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 .
*/
2022-10-04 12:21:28 +03:00
struct fwnode_handle * device_get_next_child_node ( const struct device * dev ,
2017-03-28 10:52:18 +03:00
struct fwnode_handle * child )
{
2021-06-04 19:50:47 +03:00
const struct fwnode_handle * fwnode = dev_fwnode ( dev ) ;
struct fwnode_handle * next ;
2017-03-28 10:52:18 +03:00
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
return NULL ;
2020-05-20 13:29:59 +03:00
/* Try to find a child in primary fwnode */
next = fwnode_get_next_child_node ( fwnode , child ) ;
if ( next )
return next ;
/* When no more children in primary, continue with secondary */
2022-04-08 21:48:40 +03:00
return fwnode_get_next_child_node ( fwnode - > secondary , child ) ;
2017-03-28 10:52:18 +03:00
}
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 .
*/
2022-10-04 12:21:28 +03:00
struct fwnode_handle * device_get_named_child_node ( const struct device * dev ,
2017-03-28 10:52:19 +03:00
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 .
2021-01-07 16:28:26 +03:00
*
* For fwnode node types that don ' t implement the . device_is_available ( )
* operation , this function returns true .
2017-06-06 12:37:39 +03:00
*/
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
{
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( fwnode ) )
return false ;
2021-01-07 16:28:26 +03:00
if ( ! fwnode_has_op ( fwnode , device_is_available ) )
return true ;
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
*/
2022-10-04 12:21:28 +03:00
unsigned int device_get_child_node_count ( const struct device * dev )
2014-11-04 16:03:59 +03:00
{
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
2022-10-04 12:21:29 +03:00
bool device_dma_supported ( const struct device * dev )
2015-10-29 01:50:49 +03:00
{
2022-03-31 15:54:47 +03:00
return fwnode_call_bool_op ( dev_fwnode ( dev ) , device_dma_supported ) ;
2015-10-29 01:50:49 +03:00
}
EXPORT_SYMBOL_GPL ( device_dma_supported ) ;
2022-10-04 12:21:29 +03:00
enum dev_dma_attr device_get_dma_attr ( const struct device * dev )
2015-10-29 01:50:49 +03:00
{
2022-03-31 15:54:47 +03:00
if ( ! fwnode_has_op ( dev_fwnode ( dev ) , device_get_dma_attr ) )
return DEV_DMA_NOT_SUPPORTED ;
2015-10-29 01:50:49 +03:00
2022-03-31 15:54:47 +03:00
return fwnode_call_int_op ( dev_fwnode ( dev ) , device_get_dma_attr ) ;
2015-10-29 01:50:49 +03:00
}
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 ) ;
2022-02-03 15:56:13 +03:00
/**
* fwnode_iomap - Maps the memory mapped IO for a given fwnode
* @ fwnode : Pointer to the firmware node
* @ index : Index of the IO range
*
* Returns a pointer to the mapped memory .
*/
void __iomem * fwnode_iomap ( struct fwnode_handle * fwnode , int index )
{
2022-03-31 15:54:49 +03:00
return fwnode_call_ptr_op ( fwnode , iomap , index ) ;
2022-02-03 15:56:13 +03:00
}
EXPORT_SYMBOL ( fwnode_iomap ) ;
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 .
*/
2021-06-04 19:50:47 +03:00
int fwnode_irq_get ( const struct fwnode_handle * fwnode , unsigned int index )
2018-01-18 15:31:40 +03:00
{
2022-03-31 15:54:50 +03:00
return fwnode_call_int_op ( fwnode , irq_get , index ) ;
2018-01-18 15:31:40 +03:00
}
EXPORT_SYMBOL ( fwnode_irq_get ) ;
2022-01-28 14:44:25 +03:00
/**
* fwnode_irq_get_byname - Get IRQ from a fwnode using its name
* @ fwnode : Pointer to the firmware node
* @ name : IRQ name
*
* Description :
* Find a match to the string @ name in the ' interrupt - names ' string array
* in _DSD for ACPI , or of_node for Device Tree . Then get the Linux IRQ
* number of the IRQ resource corresponding to the index of the matched
* string .
*
* Return :
* Linux IRQ number on success , or negative errno otherwise .
*/
int fwnode_irq_get_byname ( const struct fwnode_handle * fwnode , const char * name )
{
int index ;
if ( ! name )
return - EINVAL ;
index = fwnode_property_match_string ( fwnode , " interrupt-names " , name ) ;
if ( index < 0 )
return index ;
return fwnode_irq_get ( fwnode , index ) ;
}
EXPORT_SYMBOL ( fwnode_irq_get_byname ) ;
2017-03-28 10:52:21 +03:00
/**
2018-12-18 18:52:39 +03:00
* fwnode_graph_get_next_endpoint - Get next endpoint firmware node
2017-03-28 10:52:21 +03:00
* @ 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 )
{
2021-08-07 01:09:05 +03:00
const struct fwnode_handle * parent ;
struct fwnode_handle * ep ;
/*
* If this function is in a loop and the previous iteration returned
* an endpoint from fwnode - > secondary , then we need to use the secondary
* as parent rather than @ fwnode .
*/
if ( prev )
parent = fwnode_graph_get_port_parent ( prev ) ;
else
parent = fwnode ;
2022-04-08 21:48:40 +03:00
if ( IS_ERR_OR_NULL ( parent ) )
return NULL ;
2021-08-07 01:09:05 +03:00
ep = fwnode_call_ptr_op ( parent , graph_get_next_endpoint , prev ) ;
2022-04-08 21:48:40 +03:00
if ( ep )
return ep ;
2021-08-07 01:09:05 +03:00
2022-04-08 21:48:40 +03:00
return fwnode_graph_get_next_endpoint ( parent - > secondary , NULL ) ;
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
2021-12-01 15:59:33 +03:00
static bool fwnode_graph_remote_available ( struct fwnode_handle * ep )
{
struct fwnode_handle * dev_node ;
bool available ;
dev_node = fwnode_graph_get_remote_port_parent ( ep ) ;
available = fwnode_device_is_available ( dev_node ) ;
fwnode_handle_put ( dev_node ) ;
return available ;
}
2019-04-02 13:30:37 +03:00
/**
* fwnode_graph_get_endpoint_by_id - get endpoint by port and endpoint numbers
* @ fwnode : parent fwnode_handle containing the graph
* @ port : identifier of the port node
* @ endpoint : identifier of the endpoint node under the port node
* @ flags : fwnode lookup flags
*
* Return the fwnode handle of the local endpoint corresponding the port and
* endpoint IDs or NULL if not found .
*
* If FWNODE_GRAPH_ENDPOINT_NEXT is passed in @ flags and the specified endpoint
* has not been found , look for the closest endpoint ID greater than the
* specified one and return the endpoint that corresponds to it , if present .
*
2021-12-01 15:59:30 +03:00
* Does not return endpoints that belong to disabled devices or endpoints that
* are unconnected , unless FWNODE_GRAPH_DEVICE_DISABLED is passed in @ flags .
2019-04-02 13:30:37 +03:00
*
* The returned endpoint needs to be released by calling fwnode_handle_put ( ) on
* it when it is not needed any more .
*/
struct fwnode_handle *
fwnode_graph_get_endpoint_by_id ( const struct fwnode_handle * fwnode ,
u32 port , u32 endpoint , unsigned long flags )
{
2021-12-01 15:59:34 +03:00
struct fwnode_handle * ep , * best_ep = NULL ;
2019-04-02 13:30:37 +03:00
unsigned int best_ep_id = 0 ;
bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT ;
bool enabled_only = ! ( flags & FWNODE_GRAPH_DEVICE_DISABLED ) ;
2021-12-01 15:59:34 +03:00
fwnode_graph_for_each_endpoint ( fwnode , ep ) {
2019-04-02 13:30:37 +03:00
struct fwnode_endpoint fwnode_ep = { 0 } ;
int ret ;
2021-12-01 15:59:33 +03:00
if ( enabled_only & & ! fwnode_graph_remote_available ( ep ) )
continue ;
2019-04-02 13:30:37 +03:00
ret = fwnode_graph_parse_endpoint ( ep , & fwnode_ep ) ;
if ( ret < 0 )
continue ;
if ( fwnode_ep . port ! = port )
continue ;
if ( fwnode_ep . id = = endpoint )
return ep ;
if ( ! endpoint_next )
continue ;
/*
* If the endpoint that has just been found is not the first
* matching one and the ID of the one found previously is closer
* to the requested endpoint ID , skip it .
*/
if ( fwnode_ep . id < endpoint | |
( best_ep & & best_ep_id < fwnode_ep . id ) )
continue ;
fwnode_handle_put ( best_ep ) ;
best_ep = fwnode_handle_get ( ep ) ;
best_ep_id = fwnode_ep . id ;
}
2021-08-07 01:09:06 +03:00
return best_ep ;
2019-04-02 13:30:37 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_endpoint_by_id ) ;
2021-12-01 15:59:33 +03:00
/**
* fwnode_graph_get_endpoint_count - Count endpoints on a device node
* @ fwnode : The node related to a device
* @ flags : fwnode lookup flags
* Count endpoints in a device node .
*
* If FWNODE_GRAPH_DEVICE_DISABLED flag is specified , also unconnected endpoints
* and endpoints connected to disabled devices are counted .
*/
unsigned int fwnode_graph_get_endpoint_count ( struct fwnode_handle * fwnode ,
unsigned long flags )
{
struct fwnode_handle * ep ;
unsigned int count = 0 ;
fwnode_graph_for_each_endpoint ( fwnode , ep ) {
if ( flags & FWNODE_GRAPH_DEVICE_DISABLED | |
fwnode_graph_remote_available ( ep ) )
count + + ;
}
return count ;
}
EXPORT_SYMBOL_GPL ( fwnode_graph_get_endpoint_count ) ;
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 ) ;
2017-12-13 10:20:49 +03:00
2022-09-22 16:54:10 +03:00
const void * device_get_match_data ( const struct device * dev )
2017-12-13 10:20:49 +03:00
{
2018-02-09 18:38:36 +03:00
return fwnode_call_ptr_op ( dev_fwnode ( dev ) , device_get_match_data , dev ) ;
2017-12-13 10:20:49 +03:00
}
EXPORT_SYMBOL_GPL ( device_get_match_data ) ;
2020-09-07 15:05:31 +03:00
2022-10-04 12:21:26 +03:00
static unsigned int fwnode_graph_devcon_matches ( const struct fwnode_handle * fwnode ,
2022-04-23 01:23:45 +03:00
const char * con_id , void * data ,
devcon_match_fn_t match ,
void * * matches ,
unsigned int matches_len )
2020-09-07 15:05:31 +03:00
{
struct fwnode_handle * node ;
struct fwnode_handle * ep ;
2022-04-23 01:23:45 +03:00
unsigned int count = 0 ;
2020-09-07 15:05:31 +03:00
void * ret ;
fwnode_graph_for_each_endpoint ( fwnode , ep ) {
2022-04-23 01:23:45 +03:00
if ( matches & & count > = matches_len ) {
fwnode_handle_put ( ep ) ;
break ;
}
2020-09-07 15:05:31 +03:00
node = fwnode_graph_get_remote_port_parent ( ep ) ;
2021-12-01 15:59:29 +03:00
if ( ! fwnode_device_is_available ( node ) ) {
fwnode_handle_put ( node ) ;
2020-09-07 15:05:31 +03:00
continue ;
2021-12-01 15:59:29 +03:00
}
2020-09-07 15:05:31 +03:00
ret = match ( node , con_id , data ) ;
fwnode_handle_put ( node ) ;
if ( ret ) {
2022-04-23 01:23:45 +03:00
if ( matches )
matches [ count ] = ret ;
count + + ;
2020-09-07 15:05:31 +03:00
}
}
2022-04-23 01:23:45 +03:00
return count ;
2020-09-07 15:05:31 +03:00
}
2022-10-04 12:21:26 +03:00
static unsigned int fwnode_devcon_matches ( const struct fwnode_handle * fwnode ,
2022-04-23 01:23:45 +03:00
const char * con_id , void * data ,
devcon_match_fn_t match ,
void * * matches ,
unsigned int matches_len )
2020-09-07 15:05:31 +03:00
{
struct fwnode_handle * node ;
2022-04-23 01:23:45 +03:00
unsigned int count = 0 ;
unsigned int i ;
2020-09-07 15:05:31 +03:00
void * ret ;
for ( i = 0 ; ; i + + ) {
2022-04-23 01:23:45 +03:00
if ( matches & & count > = matches_len )
break ;
2020-09-07 15:05:31 +03:00
node = fwnode_find_reference ( fwnode , con_id , i ) ;
if ( IS_ERR ( node ) )
break ;
ret = match ( node , NULL , data ) ;
fwnode_handle_put ( node ) ;
2022-04-23 01:23:45 +03:00
if ( ret ) {
if ( matches )
matches [ count ] = ret ;
count + + ;
}
2020-09-07 15:05:31 +03:00
}
2022-04-23 01:23:45 +03:00
return count ;
2020-09-07 15:05:31 +03:00
}
/**
* fwnode_connection_find_match - Find connection from a device node
* @ fwnode : Device node with the connection
* @ con_id : Identifier for the connection
* @ data : Data for the match function
* @ match : Function to check and convert the connection description
*
* Find a connection with unique identifier @ con_id between @ fwnode and another
* device node . @ match will be used to convert the connection description to
* data the caller is expecting to be returned .
*/
2022-10-04 12:21:26 +03:00
void * fwnode_connection_find_match ( const struct fwnode_handle * fwnode ,
2020-09-07 15:05:31 +03:00
const char * con_id , void * data ,
devcon_match_fn_t match )
{
2022-04-23 01:23:46 +03:00
unsigned int count ;
2020-09-07 15:05:31 +03:00
void * ret ;
if ( ! fwnode | | ! match )
return NULL ;
2022-04-23 01:23:46 +03:00
count = fwnode_graph_devcon_matches ( fwnode , con_id , data , match , & ret , 1 ) ;
if ( count )
2020-09-07 15:05:31 +03:00
return ret ;
2022-04-23 01:23:46 +03:00
count = fwnode_devcon_matches ( fwnode , con_id , data , match , & ret , 1 ) ;
return count ? ret : NULL ;
2020-09-07 15:05:31 +03:00
}
EXPORT_SYMBOL_GPL ( fwnode_connection_find_match ) ;
2022-04-23 01:23:45 +03:00
/**
* fwnode_connection_find_matches - Find connections from a device node
* @ fwnode : Device node with the connection
* @ con_id : Identifier for the connection
* @ data : Data for the match function
* @ match : Function to check and convert the connection description
* @ matches : ( Optional ) array of pointers to fill with matches
* @ matches_len : Length of @ matches
*
* Find up to @ matches_len connections with unique identifier @ con_id between
* @ fwnode and other device nodes . @ match will be used to convert the
* connection description to data the caller is expecting to be returned
* through the @ matches array .
* If @ matches is NULL @ matches_len is ignored and the total number of resolved
* matches is returned .
*
* Return : Number of matches resolved , or negative errno .
*/
2022-10-04 12:21:26 +03:00
int fwnode_connection_find_matches ( const struct fwnode_handle * fwnode ,
2022-04-23 01:23:45 +03:00
const char * con_id , void * data ,
devcon_match_fn_t match ,
void * * matches , unsigned int matches_len )
{
unsigned int count_graph ;
unsigned int count_ref ;
if ( ! fwnode | | ! match )
return - EINVAL ;
count_graph = fwnode_graph_devcon_matches ( fwnode , con_id , data , match ,
matches , matches_len ) ;
if ( matches ) {
matches + = count_graph ;
matches_len - = count_graph ;
}
count_ref = fwnode_devcon_matches ( fwnode , con_id , data , match ,
matches , matches_len ) ;
return count_graph + count_ref ;
}
EXPORT_SYMBOL_GPL ( fwnode_connection_find_matches ) ;