@ -679,6 +679,130 @@ int fdtdec_get_bool(const void *blob, int node, const char *prop_name)
return cell ! = NULL ;
}
int fdtdec_parse_phandle_with_args ( const void * blob , int src_node ,
const char * list_name ,
const char * cells_name ,
int cell_count , int index ,
struct fdtdec_phandle_args * out_args )
{
const __be32 * list , * list_end ;
int rc = 0 , size , cur_index = 0 ;
uint32_t count = 0 ;
int node = - 1 ;
int phandle ;
/* Retrieve the phandle list property */
list = fdt_getprop ( blob , src_node , list_name , & size ) ;
if ( ! list )
return - ENOENT ;
list_end = list + size / sizeof ( * list ) ;
/* Loop over the phandles until all the requested entry is found */
while ( list < list_end ) {
rc = - EINVAL ;
count = 0 ;
/*
* If phandle is 0 , then it is an empty entry with no
* arguments . Skip forward to the next entry .
*/
phandle = be32_to_cpup ( list + + ) ;
if ( phandle ) {
/*
* Find the provider node and parse the # * - cells
* property to determine the argument length .
*
* This is not needed if the cell count is hard - coded
* ( i . e . cells_name not set , but cell_count is set ) ,
* except when we ' re going to return the found node
* below .
*/
if ( cells_name | | cur_index = = index ) {
node = fdt_node_offset_by_phandle ( blob ,
phandle ) ;
if ( ! node ) {
debug ( " %s: could not find phandle \n " ,
fdt_get_name ( blob , src_node ,
NULL ) ) ;
goto err ;
}
}
if ( cells_name ) {
count = fdtdec_get_int ( blob , node , cells_name ,
- 1 ) ;
if ( count = = - 1 ) {
debug ( " %s: could not get %s for %s \n " ,
fdt_get_name ( blob , src_node ,
NULL ) ,
cells_name ,
fdt_get_name ( blob , node ,
NULL ) ) ;
goto err ;
}
} else {
count = cell_count ;
}
/*
* Make sure that the arguments actually fit in the
* remaining property data length
*/
if ( list + count > list_end ) {
debug ( " %s: arguments longer than property \n " ,
fdt_get_name ( blob , src_node , NULL ) ) ;
goto err ;
}
}
/*
* All of the error cases above bail out of the loop , so at
* this point , the parsing is successful . If the requested
* index matches , then fill the out_args structure and return ,
* or return - ENOENT for an empty entry .
*/
rc = - ENOENT ;
if ( cur_index = = index ) {
if ( ! phandle )
goto err ;
if ( out_args ) {
int i ;
if ( count > MAX_PHANDLE_ARGS ) {
debug ( " %s: too many arguments %d \n " ,
fdt_get_name ( blob , src_node ,
NULL ) , count ) ;
count = MAX_PHANDLE_ARGS ;
}
out_args - > node = node ;
out_args - > args_count = count ;
for ( i = 0 ; i < count ; i + + ) {
out_args - > args [ i ] =
be32_to_cpup ( list + + ) ;
}
}
/* Found it! return success */
return 0 ;
}
node = - 1 ;
list + = count ;
cur_index + + ;
}
/*
* Result will be one of :
* - ENOENT : index is for empty phandle
* - EINVAL : parsing error on data
* [ 1. . n ] : Number of phandle ( count mode ; when index = - 1 )
*/
rc = index < 0 ? cur_index : - ENOENT ;
err :
return rc ;
}
/**
* Decode a list of GPIOs from an FDT . This creates a list of GPIOs with no
* terminating item .