This test script try to do whitebox testing for gpio subsystem( based on gpiolib). It manipulate gpio-mockup device through sysfs provided and check the result from debugfs. Test the following things: 1. Add single, multi gpiochip with the checking of overlap. 2. Test direction and output value for valid pin. 3. Test dynamic allocation of gpio base. Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian@xxxxxxxxxx> --- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/gpio/gpio.sh | 238 +++++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100755 tools/testing/selftests/gpio/gpio.sh diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index cfe1213..df0b81d 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -5,6 +5,7 @@ TARGETS += exec TARGETS += firmware TARGETS += ftrace TARGETS += futex +TARGETS += gpio TARGETS += kcmp TARGETS += membarrier TARGETS += memfd diff --git a/tools/testing/selftests/gpio/gpio.sh b/tools/testing/selftests/gpio/gpio.sh new file mode 100755 index 0000000..05e109e --- /dev/null +++ b/tools/testing/selftests/gpio/gpio.sh @@ -0,0 +1,238 @@ +#!/bin/bash + +module="gpio-mockup" + +SYSFS= +GPIO_SYSFS= +GPIO_DRV_SYSFS= +DEBUGFS= +GPIO_DEBUGFS= + +prerequisite() +{ + msg="skip all tests:" + + if [ $UID != 0 ]; then + echo $msg must be run as root >&2 + exit 0 + fi + + SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` + if [ ! -d "$SYSFS" ]; then + echo $msg sysfs is not mounted >&2 + exit 0 + fi + GPIO_SYSFS=`echo $SYSFS/class/gpio` + GPIO_DRV_SYSFS=`echo $SYSFS/devices/platform/$module/gpio` + + DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` + if [ ! -d "$DEBUGFS" ]; then + echo $msg debugfs is not mounted >&2 + exit 0 + fi + GPIO_DEBUGFS=`echo $DEBUGFS/gpio` + +} + +insert_module() +{ + if modprobe -q $module $1; then + echo -n "" + else + echo $msg insmod $module failed >&2 + exit 0 + fi +} + +remove_module() +{ + modprobe -r -q $module +} + +die() +{ + remove_module + exit 1 +} + +gpio_test() +{ + param=$1 + if [ X$2 != X ]; then + invalid_pin=$2 + fi + if [ X$param = X ]; then + insert_module + else + insert_module "conf=$param" + fi + + echo -n "GPIO $module test with base,ngpio configure<" + if [ X$param = X ]; then + echo "(default)>: "; + else + echo "$param>: " + fi + printf "%-10s %-5s %-5s\n" name base ngpio + gpiochip=`ls -d $GPIO_DRV_SYSFS/gpiochip* 2>/dev/null` + if [ X"$gpiochip" = X ]; then + echo "no gpiochip" + else + for chip in $gpiochip; do + name=`basename $chip` + base=`cat $chip/base` + ngpio=`cat $chip/ngpio` + printf "%-10s %-5s %-5s\n" $name $base $ngpio + if [ $ngpio = "0" ]; then + echo "number of gpio is zero is not allowed". + fi + test_one_pin $base + test_one_pin $(($base + $ngpio - 1)) + test_one_pin $((( RANDOM % $ngpio ) + $base )) + if [ X$invalid_pin != X ]; then + test_one_pin_fail $invalid_pin + fi + done + fi + remove_module +} + +gpio_test_fail() +{ + param=$1 + + insert_module "conf=$param" + echo -n "GPIO $module fail test with base,ngpio configure<$param>: " + gpiochip=`ls -d $GPIO_DRV_SYSFS/gpiochip* 2>/dev/null` + if [ X"$gpiochip" = X ]; then + echo "successful" + else + echo "fail" + die + fi + remove_module +} + +is_consistent() +{ + val= + + active_low_sysfs=`cat $GPIO_SYSFS/gpio$nr/active_low` + val_sysfs=`cat $GPIO_SYSFS/gpio$nr/value` + dir_sysfs=`cat $GPIO_SYSFS/gpio$nr/direction` + + gpio_this_debugfs=`cat $GPIO_DEBUGFS |grep "gpio-$nr" | sed "s/(.*)//g"` + dir_debugfs=`echo $gpio_this_debugfs | awk '{print $2}'` + val_debugfs=`echo $gpio_this_debugfs | awk '{print $3}'` + if [ $val_debugfs = "lo" ]; then + val=0 + elif [ $val_debugfs = "hi" ]; then + val=1 + fi + + if [ $active_low_sysfs = "1" ]; then + if [ $val = "0" ]; then + val="1" + else + val="0" + fi + fi + + if [ $val_sysfs = $val ] && [ $dir_sysfs = $dir_debugfs ]; then + echo -n "." + else + echo "test fail, exit" + die + fi +} + +test_pin_logic() +{ + nr=$1 + direction=$2 + active_low=$3 + value=$4 + + echo $direction > $GPIO_SYSFS/gpio$nr/direction + echo $active_low > $GPIO_SYSFS/gpio$nr/active_low + if [ $direction = "out" ]; then + echo $value > $GPIO_SYSFS/gpio$nr/value + fi + is_consistent $nr +} + +test_one_pin() +{ + nr=$1 + + echo -n "test pin<$nr>" + + echo $nr > $GPIO_SYSFS/export 2>/dev/null + + if [ X$? != X0 ]; then + echo "test GPIO pin $nr failed" + die + fi + + #"Checking if the sysfs is consistent with debugfs: " + is_consistent $nr + + #"Checking the logic of active_low: " + test_pin_logic $nr out 1 1 + test_pin_logic $nr out 1 0 + test_pin_logic $nr out 0 1 + test_pin_logic $nr out 0 0 + + #"Checking the logic of direction: " + test_pin_logic $nr in 1 1 + test_pin_logic $nr out 1 0 + test_pin_logic $nr low 0 1 + test_pin_logic $nr high 0 0 + + echo $nr > $GPIO_SYSFS/unexport + + echo "successful" +} + +test_one_pin_fail() +{ + nr=$1 + + echo $nr > $GPIO_SYSFS/export 2>/dev/null + + if [ X$? != X0 ]; then + echo "test invalid pin $nr successful" + else + echo "test invalid pin $nr failed" + echo $nr > $GPIO_SYSFS/unexport 2>/dev/null + die + fi +} + +prerequisite + +#basically +gpio_test +gpio_test "0,32" 33 +gpio_test "0,32,32,16" 50 +gpio_test "0,32,40,16,32,5" 38 +#test dynamic allocation of gpio +gpio_test "-1,32" +gpio_test "-1,32,32,16" 31 +gpio_test "-1,32,40,16,-1,5" 38 +#error test +#zero number of gpio +gpio_test_fail "0,0" +#base conflict +gpio_test_fail "0,32,0,1" +#range overlap +gpio_test_fail "0,32,30,5" +gpio_test_fail "0,32,1,5" +gpio_test_fail "10,32,9,5" +gpio_test_fail "10,32,30,5" +gpio_test_fail "0,32,40,16,39,5" +gpio_test_fail "0,32,40,16,30,5" +gpio_test_fail "0,32,40,16,30,11" +gpio_test_fail "0,32,40,16,20,1" + +echo GPIO test PASS -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html