2011-12-12 09:25:57 -07:00
/*
* Self tests for device tree subsystem
*/
2013-02-12 21:19:37 +00:00
# define pr_fmt(fmt) "### dt-test ### " fmt
2011-12-12 09:25:57 -07:00
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/errno.h>
# include <linux/module.h>
# include <linux/of.h>
2013-10-11 22:04:23 +01:00
# include <linux/of_irq.h>
2011-12-12 09:25:57 -07:00
# include <linux/list.h>
# include <linux/mutex.h>
# include <linux/slab.h>
# include <linux/device.h>
2013-10-11 22:04:23 +01:00
static struct selftest_results {
int passed ;
int failed ;
} selftest_results ;
2011-12-12 09:25:57 -07:00
# define selftest(result, fmt, ...) { \
2013-02-12 21:19:37 +00:00
if ( ! ( result ) ) { \
2013-10-11 22:04:23 +01:00
selftest_results . failed + + ; \
pr_err ( " FAIL %s():%i " fmt , __func__ , __LINE__ , # # __VA_ARGS__ ) ; \
2013-02-12 21:19:37 +00:00
} else { \
2013-10-11 22:04:23 +01:00
selftest_results . passed + + ; \
pr_debug ( " pass %s():%i \n " , __func__ , __LINE__ ) ; \
2013-02-12 21:19:37 +00:00
} \
2011-12-12 09:25:57 -07:00
}
static void __init of_selftest_parse_phandle_with_args ( void )
{
struct device_node * np ;
struct of_phandle_args args ;
2013-02-12 21:19:37 +00:00
int i , rc ;
2011-12-12 09:25:57 -07:00
np = of_find_node_by_path ( " /testcase-data/phandle-tests/consumer-a " ) ;
if ( ! np ) {
pr_err ( " missing testcase data \n " ) ;
return ;
}
2013-02-10 22:57:21 +00:00
rc = of_count_phandle_with_args ( np , " phandle-list " , " #phandle-cells " ) ;
selftest ( rc = = 7 , " of_count_phandle_with_args() returned %i, expected 7 \n " , rc ) ;
2013-02-12 17:41:22 +00:00
for ( i = 0 ; i < 8 ; i + + ) {
2011-12-12 09:25:57 -07:00
bool passed = true ;
rc = of_parse_phandle_with_args ( np , " phandle-list " ,
" #phandle-cells " , i , & args ) ;
/* Test the values from tests-phandle.dtsi */
switch ( i ) {
case 0 :
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = ( i + 1 ) ) ;
break ;
case 1 :
passed & = ! rc ;
passed & = ( args . args_count = = 2 ) ;
passed & = ( args . args [ 0 ] = = ( i + 1 ) ) ;
passed & = ( args . args [ 1 ] = = 0 ) ;
break ;
case 2 :
passed & = ( rc = = - ENOENT ) ;
break ;
case 3 :
passed & = ! rc ;
passed & = ( args . args_count = = 3 ) ;
passed & = ( args . args [ 0 ] = = ( i + 1 ) ) ;
passed & = ( args . args [ 1 ] = = 4 ) ;
passed & = ( args . args [ 2 ] = = 3 ) ;
break ;
case 4 :
passed & = ! rc ;
passed & = ( args . args_count = = 2 ) ;
passed & = ( args . args [ 0 ] = = ( i + 1 ) ) ;
passed & = ( args . args [ 1 ] = = 100 ) ;
break ;
case 5 :
passed & = ! rc ;
passed & = ( args . args_count = = 0 ) ;
break ;
case 6 :
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = ( i + 1 ) ) ;
break ;
case 7 :
2013-02-12 21:19:37 +00:00
passed & = ( rc = = - ENOENT ) ;
2011-12-12 09:25:57 -07:00
break ;
default :
passed = false ;
}
2013-02-12 21:19:37 +00:00
selftest ( passed , " index %i - data error on node %s rc=%i \n " ,
i , args . np - > full_name , rc ) ;
2011-12-12 09:25:57 -07:00
}
/* Check for missing list property */
rc = of_parse_phandle_with_args ( np , " phandle-list-missing " ,
" #phandle-cells " , 0 , & args ) ;
2013-02-12 21:19:37 +00:00
selftest ( rc = = - ENOENT , " expected:%i got:%i \n " , - ENOENT , rc ) ;
2013-02-10 22:57:21 +00:00
rc = of_count_phandle_with_args ( np , " phandle-list-missing " ,
" #phandle-cells " ) ;
selftest ( rc = = - ENOENT , " expected:%i got:%i \n " , - ENOENT , rc ) ;
2011-12-12 09:25:57 -07:00
/* Check for missing cells property */
rc = of_parse_phandle_with_args ( np , " phandle-list " ,
" #phandle-cells-missing " , 0 , & args ) ;
2013-02-12 21:19:37 +00:00
selftest ( rc = = - EINVAL , " expected:%i got:%i \n " , - EINVAL , rc ) ;
2013-02-10 22:57:21 +00:00
rc = of_count_phandle_with_args ( np , " phandle-list " ,
" #phandle-cells-missing " ) ;
selftest ( rc = = - EINVAL , " expected:%i got:%i \n " , - EINVAL , rc ) ;
2011-12-12 09:25:57 -07:00
/* Check for bad phandle in list */
rc = of_parse_phandle_with_args ( np , " phandle-list-bad-phandle " ,
" #phandle-cells " , 0 , & args ) ;
2013-02-12 21:19:37 +00:00
selftest ( rc = = - EINVAL , " expected:%i got:%i \n " , - EINVAL , rc ) ;
2013-02-10 22:57:21 +00:00
rc = of_count_phandle_with_args ( np , " phandle-list-bad-phandle " ,
" #phandle-cells " ) ;
selftest ( rc = = - EINVAL , " expected:%i got:%i \n " , - EINVAL , rc ) ;
2011-12-12 09:25:57 -07:00
/* Check for incorrectly formed argument list */
rc = of_parse_phandle_with_args ( np , " phandle-list-bad-args " ,
" #phandle-cells " , 1 , & args ) ;
2013-02-12 21:19:37 +00:00
selftest ( rc = = - EINVAL , " expected:%i got:%i \n " , - EINVAL , rc ) ;
2013-02-10 22:57:21 +00:00
rc = of_count_phandle_with_args ( np , " phandle-list-bad-args " ,
" #phandle-cells " ) ;
selftest ( rc = = - EINVAL , " expected:%i got:%i \n " , - EINVAL , rc ) ;
2011-12-12 09:25:57 -07:00
}
2011-12-12 09:25:58 -07:00
static void __init of_selftest_property_match_string ( void )
{
struct device_node * np ;
int rc ;
np = of_find_node_by_path ( " /testcase-data/phandle-tests/consumer-a " ) ;
if ( ! np ) {
pr_err ( " No testcase data in device tree \n " ) ;
return ;
}
rc = of_property_match_string ( np , " phandle-list-names " , " first " ) ;
selftest ( rc = = 0 , " first expected:0 got:%i \n " , rc ) ;
rc = of_property_match_string ( np , " phandle-list-names " , " second " ) ;
selftest ( rc = = 1 , " second expected:0 got:%i \n " , rc ) ;
rc = of_property_match_string ( np , " phandle-list-names " , " third " ) ;
selftest ( rc = = 2 , " third expected:0 got:%i \n " , rc ) ;
rc = of_property_match_string ( np , " phandle-list-names " , " fourth " ) ;
selftest ( rc = = - ENODATA , " unmatched string; rc=%i " , rc ) ;
rc = of_property_match_string ( np , " missing-property " , " blah " ) ;
selftest ( rc = = - EINVAL , " missing property; rc=%i " , rc ) ;
rc = of_property_match_string ( np , " empty-property " , " blah " ) ;
selftest ( rc = = - ENODATA , " empty property; rc=%i " , rc ) ;
rc = of_property_match_string ( np , " unterminated-string " , " blah " ) ;
selftest ( rc = = - EILSEQ , " unterminated string; rc=%i " , rc ) ;
}
2013-10-11 22:04:23 +01:00
static void __init of_selftest_parse_interrupts ( void )
{
struct device_node * np ;
struct of_phandle_args args ;
int i , rc ;
np = of_find_node_by_path ( " /testcase-data/interrupts/interrupts0 " ) ;
if ( ! np ) {
pr_err ( " missing testcase data \n " ) ;
return ;
}
for ( i = 0 ; i < 4 ; i + + ) {
bool passed = true ;
args . args_count = 0 ;
rc = of_irq_parse_one ( np , i , & args ) ;
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = ( i + 1 ) ) ;
selftest ( passed , " index %i - data error on node %s rc=%i \n " ,
i , args . np - > full_name , rc ) ;
}
of_node_put ( np ) ;
np = of_find_node_by_path ( " /testcase-data/interrupts/interrupts1 " ) ;
if ( ! np ) {
pr_err ( " missing testcase data \n " ) ;
return ;
}
for ( i = 0 ; i < 4 ; i + + ) {
bool passed = true ;
args . args_count = 0 ;
rc = of_irq_parse_one ( np , i , & args ) ;
/* Test the values from tests-phandle.dtsi */
switch ( i ) {
case 0 :
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = 9 ) ;
break ;
case 1 :
passed & = ! rc ;
passed & = ( args . args_count = = 3 ) ;
passed & = ( args . args [ 0 ] = = 10 ) ;
passed & = ( args . args [ 1 ] = = 11 ) ;
passed & = ( args . args [ 2 ] = = 12 ) ;
break ;
case 2 :
passed & = ! rc ;
passed & = ( args . args_count = = 2 ) ;
passed & = ( args . args [ 0 ] = = 13 ) ;
passed & = ( args . args [ 1 ] = = 14 ) ;
break ;
case 3 :
passed & = ! rc ;
passed & = ( args . args_count = = 2 ) ;
passed & = ( args . args [ 0 ] = = 15 ) ;
passed & = ( args . args [ 1 ] = = 16 ) ;
break ;
default :
passed = false ;
}
selftest ( passed , " index %i - data error on node %s rc=%i \n " ,
i , args . np - > full_name , rc ) ;
}
of_node_put ( np ) ;
}
2013-09-19 16:47:37 -05:00
static void __init of_selftest_parse_interrupts_extended ( void )
{
struct device_node * np ;
struct of_phandle_args args ;
int i , rc ;
np = of_find_node_by_path ( " /testcase-data/interrupts/interrupts-extended0 " ) ;
if ( ! np ) {
pr_err ( " missing testcase data \n " ) ;
return ;
}
for ( i = 0 ; i < 7 ; i + + ) {
bool passed = true ;
rc = of_irq_parse_one ( np , i , & args ) ;
/* Test the values from tests-phandle.dtsi */
switch ( i ) {
case 0 :
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = 1 ) ;
break ;
case 1 :
passed & = ! rc ;
passed & = ( args . args_count = = 3 ) ;
passed & = ( args . args [ 0 ] = = 2 ) ;
passed & = ( args . args [ 1 ] = = 3 ) ;
passed & = ( args . args [ 2 ] = = 4 ) ;
break ;
case 2 :
passed & = ! rc ;
passed & = ( args . args_count = = 2 ) ;
passed & = ( args . args [ 0 ] = = 5 ) ;
passed & = ( args . args [ 1 ] = = 6 ) ;
break ;
case 3 :
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = 9 ) ;
break ;
case 4 :
passed & = ! rc ;
passed & = ( args . args_count = = 3 ) ;
passed & = ( args . args [ 0 ] = = 10 ) ;
passed & = ( args . args [ 1 ] = = 11 ) ;
passed & = ( args . args [ 2 ] = = 12 ) ;
break ;
case 5 :
passed & = ! rc ;
passed & = ( args . args_count = = 2 ) ;
passed & = ( args . args [ 0 ] = = 13 ) ;
passed & = ( args . args [ 1 ] = = 14 ) ;
break ;
case 6 :
passed & = ! rc ;
passed & = ( args . args_count = = 1 ) ;
passed & = ( args . args [ 0 ] = = 15 ) ;
break ;
default :
passed = false ;
}
selftest ( passed , " index %i - data error on node %s rc=%i \n " ,
i , args . np - > full_name , rc ) ;
}
of_node_put ( np ) ;
}
2011-12-12 09:25:57 -07:00
static int __init of_selftest ( void )
{
struct device_node * np ;
np = of_find_node_by_path ( " /testcase-data/phandle-tests/consumer-a " ) ;
if ( ! np ) {
pr_info ( " No testcase data in device tree; not running tests \n " ) ;
return 0 ;
}
of_node_put ( np ) ;
pr_info ( " start of selftest - you will see error messages \n " ) ;
of_selftest_parse_phandle_with_args ( ) ;
2011-12-12 09:25:58 -07:00
of_selftest_property_match_string ( ) ;
2013-10-11 22:04:23 +01:00
of_selftest_parse_interrupts ( ) ;
2013-09-19 16:47:37 -05:00
of_selftest_parse_interrupts_extended ( ) ;
2013-10-11 22:04:23 +01:00
pr_info ( " end of selftest - %i passed, %i failed \n " ,
selftest_results . passed , selftest_results . failed ) ;
2011-12-12 09:25:57 -07:00
return 0 ;
}
late_initcall ( of_selftest ) ;