18bc395a6SKent Gibson#!/bin/bash -efu 2b2441318SGreg Kroah-Hartman# SPDX-License-Identifier: GPL-2.0 322f6592bSBamvor Jian Zhang 422f6592bSBamvor Jian Zhang#exit status 58bc395a6SKent Gibson#0: success 68bc395a6SKent Gibson#1: fail 78bc395a6SKent Gibson#4: skip test - including run as non-root user 822f6592bSBamvor Jian Zhang 98bc395a6SKent GibsonBASE=${0%/*} 1022f6592bSBamvor Jian ZhangDEBUGFS= 1122f6592bSBamvor Jian ZhangGPIO_DEBUGFS= 128bc395a6SKent Gibsondev_type="cdev" 138bc395a6SKent Gibsonmodule="gpio-mockup" 148bc395a6SKent Gibsonverbose= 158bc395a6SKent Gibsonfull_test= 168bc395a6SKent Gibsonrandom= 17*10f33652SKent Gibsonuapi_opt= 188bc395a6SKent Gibsonactive_opt= 198bc395a6SKent Gibsonbias_opt= 208bc395a6SKent Gibsonline_set_pid= 2122f6592bSBamvor Jian Zhang 228bc395a6SKent Gibson# Kselftest return codes 238bc395a6SKent Gibsonksft_fail=1 24bd1bf88cSShuah Khan (Samsung OSG)ksft_skip=4 25bd1bf88cSShuah Khan (Samsung OSG) 2622f6592bSBamvor Jian Zhangusage() 2722f6592bSBamvor Jian Zhang{ 2822f6592bSBamvor Jian Zhang echo "Usage:" 298bc395a6SKent Gibson echo "$0 [-frv] [-t type]" 308bc395a6SKent Gibson echo "-f: full test (minimal set run by default)" 318bc395a6SKent Gibson echo "-r: test random lines as well as fence posts" 328bc395a6SKent Gibson echo "-t: interface type:" 338bc395a6SKent Gibson echo " cdev (character device ABI) - default" 34*10f33652SKent Gibson echo " cdev_v1 (deprecated character device ABI)" 358bc395a6SKent Gibson echo " sysfs (deprecated SYSFS ABI)" 368bc395a6SKent Gibson echo "-v: verbose progress reporting" 378bc395a6SKent Gibson exit $ksft_fail 388bc395a6SKent Gibson} 398bc395a6SKent Gibson 408bc395a6SKent Gibsonskip() 418bc395a6SKent Gibson{ 428bc395a6SKent Gibson echo "$*" >&2 438bc395a6SKent Gibson echo "GPIO $module test SKIP" 448bc395a6SKent Gibson exit $ksft_skip 4522f6592bSBamvor Jian Zhang} 4622f6592bSBamvor Jian Zhang 4722f6592bSBamvor Jian Zhangprerequisite() 4822f6592bSBamvor Jian Zhang{ 498bc395a6SKent Gibson [ $(id -u) -eq 0 ] || skip "must be run as root" 5022f6592bSBamvor Jian Zhang 518bc395a6SKent Gibson DEBUGFS=$(grep -w debugfs /proc/mounts | cut -f2 -d' ') 528bc395a6SKent Gibson [ -d "$DEBUGFS" ] || skip "debugfs is not mounted" 538bc395a6SKent Gibson 548bc395a6SKent Gibson GPIO_DEBUGFS=$DEBUGFS/$module 5522f6592bSBamvor Jian Zhang} 5622f6592bSBamvor Jian Zhang 5722f6592bSBamvor Jian Zhangremove_module() 5822f6592bSBamvor Jian Zhang{ 5922f6592bSBamvor Jian Zhang modprobe -r -q $module 6022f6592bSBamvor Jian Zhang} 6122f6592bSBamvor Jian Zhang 628bc395a6SKent Gibsoncleanup() 6322f6592bSBamvor Jian Zhang{ 648bc395a6SKent Gibson set +e 658bc395a6SKent Gibson release_line 6622f6592bSBamvor Jian Zhang remove_module 678bc395a6SKent Gibson jobs -p | xargs -r kill > /dev/null 2>&1 6822f6592bSBamvor Jian Zhang} 6922f6592bSBamvor Jian Zhang 708bc395a6SKent Gibsonfail() 7122f6592bSBamvor Jian Zhang{ 728bc395a6SKent Gibson echo "test failed: $*" >&2 738bc395a6SKent Gibson echo "GPIO $module test FAIL" 748bc395a6SKent Gibson exit $ksft_fail 7522f6592bSBamvor Jian Zhang} 7622f6592bSBamvor Jian Zhang 778bc395a6SKent Gibsontry_insert_module() 7822f6592bSBamvor Jian Zhang{ 798bc395a6SKent Gibson modprobe -q $module "$1" || fail "insert $module failed with error $?" 8022f6592bSBamvor Jian Zhang} 8122f6592bSBamvor Jian Zhang 828bc395a6SKent Gibsonlog() 838bc395a6SKent Gibson{ 848bc395a6SKent Gibson [ -z "$verbose" ] || echo "$*" 858bc395a6SKent Gibson} 8622f6592bSBamvor Jian Zhang 878bc395a6SKent Gibson# The following line helpers, release_Line, get_line and set_line, all 888bc395a6SKent Gibson# make use of the global $chip and $offset variables. 898bc395a6SKent Gibson# 908bc395a6SKent Gibson# This implementation drives the GPIO character device (cdev) uAPI. 918bc395a6SKent Gibson# Other implementations may override these to test different uAPIs. 9222f6592bSBamvor Jian Zhang 938bc395a6SKent Gibson# Release any resources related to the line 948bc395a6SKent Gibsonrelease_line() 958bc395a6SKent Gibson{ 968bc395a6SKent Gibson [ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true 978bc395a6SKent Gibson line_set_pid= 988bc395a6SKent Gibson} 9922f6592bSBamvor Jian Zhang 1008bc395a6SKent Gibson# Read the current value of the line 1018bc395a6SKent Gibsonget_line() 1028bc395a6SKent Gibson{ 1038bc395a6SKent Gibson release_line 10422f6592bSBamvor Jian Zhang 105*10f33652SKent Gibson local cdev_opts=${uapi_opt}${active_opt} 106*10f33652SKent Gibson $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset 1078bc395a6SKent Gibson echo $? 1088bc395a6SKent Gibson} 1098bc395a6SKent Gibson 1108bc395a6SKent Gibson# Set the state of the line 1118bc395a6SKent Gibson# 1128bc395a6SKent Gibson# Changes to line configuration are provided as parameters. 1138bc395a6SKent Gibson# The line is assumed to be an output if the line value 0 or 1 is 1148bc395a6SKent Gibson# specified, else an input. 1158bc395a6SKent Gibsonset_line() 1168bc395a6SKent Gibson{ 1178bc395a6SKent Gibson local val= 1188bc395a6SKent Gibson 1198bc395a6SKent Gibson release_line 1208bc395a6SKent Gibson 1218bc395a6SKent Gibson # parse config options... 1228bc395a6SKent Gibson for option in $*; do 1238bc395a6SKent Gibson case $option in 1248bc395a6SKent Gibson active-low) 1258bc395a6SKent Gibson active_opt="-l " 12622f6592bSBamvor Jian Zhang ;; 1278bc395a6SKent Gibson active-high) 1288bc395a6SKent Gibson active_opt= 12922f6592bSBamvor Jian Zhang ;; 1308bc395a6SKent Gibson bias-none) 1318bc395a6SKent Gibson bias_opt= 13222f6592bSBamvor Jian Zhang ;; 1338bc395a6SKent Gibson pull-down) 1348bc395a6SKent Gibson bias_opt="-bpull-down " 13522f6592bSBamvor Jian Zhang ;; 1368bc395a6SKent Gibson pull-up) 1378bc395a6SKent Gibson bias_opt="-bpull-up " 13822f6592bSBamvor Jian Zhang ;; 1398bc395a6SKent Gibson 0) 1408bc395a6SKent Gibson val=0 1418bc395a6SKent Gibson ;; 1428bc395a6SKent Gibson 1) 1438bc395a6SKent Gibson val=1 14422f6592bSBamvor Jian Zhang ;; 14522f6592bSBamvor Jian Zhang esac 14622f6592bSBamvor Jian Zhang done 14722f6592bSBamvor Jian Zhang 148*10f33652SKent Gibson local cdev_opts=${uapi_opt}${active_opt} 1498bc395a6SKent Gibson if [ "$val" ]; then 1508bc395a6SKent Gibson $BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset & 1518bc395a6SKent Gibson # failure to set is detected by reading mockup and toggling values 1528bc395a6SKent Gibson line_set_pid=$! 1538bc395a6SKent Gibson # allow for gpio-mockup-cdev to launch and request line 1548bc395a6SKent Gibson # (there is limited value in checking if line has been requested) 1558bc395a6SKent Gibson sleep 0.01 1568bc395a6SKent Gibson elif [ "$bias_opt" ]; then 1578bc395a6SKent Gibson cdev_opts=${cdev_opts}${bias_opt} 1588bc395a6SKent Gibson $BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true 1598bc395a6SKent Gibson fi 1608bc395a6SKent Gibson} 1618bc395a6SKent Gibson 1628bc395a6SKent Gibsonassert_line() 1638bc395a6SKent Gibson{ 1648bc395a6SKent Gibson local val 1658bc395a6SKent Gibson # don't need any retry here as set_mock allows for propagation 1668bc395a6SKent Gibson val=$(get_line) 1678bc395a6SKent Gibson [ "$val" = "$1" ] || fail "line value is ${val:-empty} when $1 was expected" 1688bc395a6SKent Gibson} 1698bc395a6SKent Gibson 1708bc395a6SKent Gibson# The following mockup helpers all make use of the $mock_line 1718bc395a6SKent Gibsonassert_mock() 1728bc395a6SKent Gibson{ 1738bc395a6SKent Gibson local backoff_wait=10 1748bc395a6SKent Gibson local retry=0 1758bc395a6SKent Gibson local val 1768bc395a6SKent Gibson # retry allows for set propagation from uAPI to mockup 1778bc395a6SKent Gibson while true; do 1788bc395a6SKent Gibson val=$(< $mock_line) 1798bc395a6SKent Gibson [ "$val" = "$1" ] && break 1808bc395a6SKent Gibson retry=$((retry + 1)) 1818bc395a6SKent Gibson [ $retry -lt 5 ] || fail "mockup $mock_line value ${val:-empty} when $1 expected" 1828bc395a6SKent Gibson sleep $(printf "%0.2f" $((backoff_wait))e-3) 1838bc395a6SKent Gibson backoff_wait=$((backoff_wait * 2)) 1848bc395a6SKent Gibson done 1858bc395a6SKent Gibson} 1868bc395a6SKent Gibson 1878bc395a6SKent Gibsonset_mock() 1888bc395a6SKent Gibson{ 1898bc395a6SKent Gibson echo "$1" > $mock_line 1908bc395a6SKent Gibson # allow for set propagation - so we won't be in a race with set_line 1918bc395a6SKent Gibson assert_mock "$1" 1928bc395a6SKent Gibson} 1938bc395a6SKent Gibson 1948bc395a6SKent Gibson# test the functionality of a line 1958bc395a6SKent Gibson# 1968bc395a6SKent Gibson# The line is set from the mockup side and is read from the userspace side 1978bc395a6SKent Gibson# (input), and is set from the userspace side and is read from the mockup side 1988bc395a6SKent Gibson# (output). 1998bc395a6SKent Gibson# 2008bc395a6SKent Gibson# Setting the mockup pull using the userspace interface bias settings is 2018bc395a6SKent Gibson# tested where supported by the userspace interface (cdev). 2028bc395a6SKent Gibsontest_line() 2038bc395a6SKent Gibson{ 2048bc395a6SKent Gibson chip=$1 2058bc395a6SKent Gibson offset=$2 2068bc395a6SKent Gibson log "test_line $chip $offset" 2078bc395a6SKent Gibson mock_line=$GPIO_DEBUGFS/$chip/$offset 2088bc395a6SKent Gibson [ -e "$mock_line" ] || fail "missing line $chip:$offset" 2098bc395a6SKent Gibson 2108bc395a6SKent Gibson # test input active-high 2118bc395a6SKent Gibson set_mock 1 2128bc395a6SKent Gibson set_line input active-high 2138bc395a6SKent Gibson assert_line 1 2148bc395a6SKent Gibson set_mock 0 2158bc395a6SKent Gibson assert_line 0 2168bc395a6SKent Gibson set_mock 1 2178bc395a6SKent Gibson assert_line 1 2188bc395a6SKent Gibson 2198bc395a6SKent Gibson if [ "$full_test" ]; then 2208bc395a6SKent Gibson if [ "$dev_type" != "sysfs" ]; then 2218bc395a6SKent Gibson # test pulls 2228bc395a6SKent Gibson set_mock 0 2238bc395a6SKent Gibson set_line input pull-up 2248bc395a6SKent Gibson assert_line 1 2258bc395a6SKent Gibson set_mock 0 2268bc395a6SKent Gibson assert_line 0 2278bc395a6SKent Gibson 2288bc395a6SKent Gibson set_mock 1 2298bc395a6SKent Gibson set_line input pull-down 2308bc395a6SKent Gibson assert_line 0 2318bc395a6SKent Gibson set_mock 1 2328bc395a6SKent Gibson assert_line 1 2338bc395a6SKent Gibson 2348bc395a6SKent Gibson set_line bias-none 23522f6592bSBamvor Jian Zhang fi 23622f6592bSBamvor Jian Zhang 2378bc395a6SKent Gibson # test input active-low 2388bc395a6SKent Gibson set_mock 0 2398bc395a6SKent Gibson set_line active-low 2408bc395a6SKent Gibson assert_line 1 2418bc395a6SKent Gibson set_mock 1 2428bc395a6SKent Gibson assert_line 0 2438bc395a6SKent Gibson set_mock 0 2448bc395a6SKent Gibson assert_line 1 2458bc395a6SKent Gibson 2468bc395a6SKent Gibson # test output active-high 2478bc395a6SKent Gibson set_mock 1 2488bc395a6SKent Gibson set_line active-high 0 2498bc395a6SKent Gibson assert_mock 0 2508bc395a6SKent Gibson set_line 1 2518bc395a6SKent Gibson assert_mock 1 2528bc395a6SKent Gibson set_line 0 2538bc395a6SKent Gibson assert_mock 0 25422f6592bSBamvor Jian Zhang fi 25522f6592bSBamvor Jian Zhang 2568bc395a6SKent Gibson # test output active-low 2578bc395a6SKent Gibson set_mock 0 2588bc395a6SKent Gibson set_line active-low 0 2598bc395a6SKent Gibson assert_mock 1 2608bc395a6SKent Gibson set_line 1 2618bc395a6SKent Gibson assert_mock 0 2628bc395a6SKent Gibson set_line 0 2638bc395a6SKent Gibson assert_mock 1 2648bc395a6SKent Gibson 2658bc395a6SKent Gibson release_line 2668bc395a6SKent Gibson} 2678bc395a6SKent Gibson 2688bc395a6SKent Gibsontest_no_line() 2698bc395a6SKent Gibson{ 2708bc395a6SKent Gibson log test_no_line "$*" 2718bc395a6SKent Gibson [ ! -e "$GPIO_DEBUGFS/$1/$2" ] || fail "unexpected line $1:$2" 2728bc395a6SKent Gibson} 2738bc395a6SKent Gibson 2748bc395a6SKent Gibson# Load the module and check that the expected number of gpiochips, with the 2758bc395a6SKent Gibson# expected number of lines, are created and are functional. 2768bc395a6SKent Gibson# 2778bc395a6SKent Gibson# $1 is the gpio_mockup_ranges parameter for the module 2788bc395a6SKent Gibson# The remaining parameters are the number of lines, n, expected for each of 2798bc395a6SKent Gibson# the gpiochips expected to be created. 2808bc395a6SKent Gibson# 2818bc395a6SKent Gibson# For each gpiochip the fence post lines, 0 and n-1, are tested, and the 2828bc395a6SKent Gibson# line on the far side of the fence post, n, is tested to not exist. 2838bc395a6SKent Gibson# 2848bc395a6SKent Gibson# If the $random flag is set then a random line in the middle of the 2858bc395a6SKent Gibson# gpiochip is tested as well. 2868bc395a6SKent Gibsoninsmod_test() 2878bc395a6SKent Gibson{ 2888bc395a6SKent Gibson local ranges= 2898bc395a6SKent Gibson local gc= 2908bc395a6SKent Gibson local width= 2918bc395a6SKent Gibson 2928bc395a6SKent Gibson [ "${1:-}" ] || fail "missing ranges" 2938bc395a6SKent Gibson ranges=$1 ; shift 2948bc395a6SKent Gibson try_insert_module "gpio_mockup_ranges=$ranges" 2958bc395a6SKent Gibson log "GPIO $module test with ranges: <$ranges>:" 2968bc395a6SKent Gibson # e.g. /sys/kernel/debug/gpio-mockup/gpiochip1 2978bc395a6SKent Gibson gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort) 2988bc395a6SKent Gibson for chip in $gpiochip; do 2998bc395a6SKent Gibson gc=${chip##*/} 3008bc395a6SKent Gibson [ "${1:-}" ] || fail "unexpected chip - $gc" 3018bc395a6SKent Gibson width=$1 ; shift 3028bc395a6SKent Gibson test_line $gc 0 3038bc395a6SKent Gibson if [ "$random" -a $width -gt 2 ]; then 3048bc395a6SKent Gibson test_line $gc $((RANDOM % ($width - 2) + 1)) 3058bc395a6SKent Gibson fi 3068bc395a6SKent Gibson test_line $gc $(($width - 1)) 3078bc395a6SKent Gibson test_no_line $gc $width 3088bc395a6SKent Gibson done 3098bc395a6SKent Gibson [ "${1:-}" ] && fail "missing expected chip of width $1" 3108bc395a6SKent Gibson remove_module || fail "failed to remove module with error $?" 3118bc395a6SKent Gibson} 3128bc395a6SKent Gibson 3138bc395a6SKent Gibsonwhile getopts ":frvt:" opt; do 3148bc395a6SKent Gibson case $opt in 3158bc395a6SKent Gibson f) 3168bc395a6SKent Gibson full_test=true 3178bc395a6SKent Gibson ;; 3188bc395a6SKent Gibson r) 3198bc395a6SKent Gibson random=true 3208bc395a6SKent Gibson ;; 3218bc395a6SKent Gibson t) 3228bc395a6SKent Gibson dev_type=$OPTARG 3238bc395a6SKent Gibson ;; 3248bc395a6SKent Gibson v) 3258bc395a6SKent Gibson verbose=true 3268bc395a6SKent Gibson ;; 3278bc395a6SKent Gibson *) 3288bc395a6SKent Gibson usage 3298bc395a6SKent Gibson ;; 3308bc395a6SKent Gibson esac 3318bc395a6SKent Gibsondone 3328bc395a6SKent Gibsonshift $((OPTIND - 1)) 3338bc395a6SKent Gibson 3348bc395a6SKent Gibson[ "${1:-}" ] && fail "unknown argument '$1'" 3358bc395a6SKent Gibson 33622f6592bSBamvor Jian Zhangprerequisite 33722f6592bSBamvor Jian Zhang 3388bc395a6SKent Gibsontrap 'exit $ksft_fail' SIGTERM SIGINT 3398bc395a6SKent Gibsontrap cleanup EXIT 3408bc395a6SKent Gibson 3418bc395a6SKent Gibsoncase "$dev_type" in 3428bc395a6SKent Gibsonsysfs) 3438bc395a6SKent Gibson source $BASE/gpio-mockup-sysfs.sh 3448bc395a6SKent Gibson echo "WARNING: gpio sysfs ABI is deprecated." 3458bc395a6SKent Gibson ;; 346*10f33652SKent Gibsoncdev_v1) 347*10f33652SKent Gibson echo "WARNING: gpio cdev ABI v1 is deprecated." 348*10f33652SKent Gibson uapi_opt="-u1 " 349*10f33652SKent Gibson ;; 3508bc395a6SKent Gibsoncdev) 3518bc395a6SKent Gibson ;; 3528bc395a6SKent Gibson*) 3538bc395a6SKent Gibson fail "unknown interface type: $dev_type" 3548bc395a6SKent Gibson ;; 3558bc395a6SKent Gibsonesac 3568bc395a6SKent Gibson 3578bc395a6SKent Gibsonremove_module || fail "can't remove existing $module module" 3588bc395a6SKent Gibson 3598bc395a6SKent Gibson# manual gpio allocation tests fail if a physical chip already exists 3608bc395a6SKent Gibson[ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0" 3618bc395a6SKent Gibson 3628bc395a6SKent Gibsonecho "1. Module load tests" 3638bc395a6SKent Gibsonecho "1.1. dynamic allocation of gpio" 3648bc395a6SKent Gibsoninsmod_test "-1,32" 32 3658bc395a6SKent Gibsoninsmod_test "-1,23,-1,32" 23 32 3668bc395a6SKent Gibsoninsmod_test "-1,23,-1,26,-1,32" 23 26 32 3678bc395a6SKent Gibsonif [ "$full_test" ]; then 3688bc395a6SKent Gibson echo "1.2. manual allocation of gpio" 3698bc395a6SKent Gibson insmod_test "0,32" 32 3708bc395a6SKent Gibson insmod_test "0,32,32,60" 32 28 3718bc395a6SKent Gibson insmod_test "0,32,40,64,64,96" 32 24 32 3728bc395a6SKent Gibson echo "1.3. dynamic and manual allocation of gpio" 3738bc395a6SKent Gibson insmod_test "-1,32,32,62" 32 30 3748bc395a6SKent Gibson insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32 3758bc395a6SKent Gibson insmod_test "-1,32,32,60,-1,29" 32 28 29 3768bc395a6SKent Gibson insmod_test "-1,32,40,64,-1,5" 32 24 5 3778bc395a6SKent Gibson insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31 37822f6592bSBamvor Jian Zhangfi 3798bc395a6SKent Gibsonecho "2. Module load error tests" 3808bc395a6SKent Gibsonecho "2.1 gpio overflow" 38122f6592bSBamvor Jian Zhang# Currently: The max number of gpio(1024) is defined in arm architecture. 3828bc395a6SKent Gibsoninsmod_test "-1,1024" 3838bc395a6SKent Gibsonif [ "$full_test" ]; then 3848bc395a6SKent Gibson echo "2.2 no lines defined" 3858bc395a6SKent Gibson insmod_test "0,0" 3868bc395a6SKent Gibson echo "2.3 ignore range overlap" 3878bc395a6SKent Gibson insmod_test "0,32,0,1" 32 3888bc395a6SKent Gibson insmod_test "0,32,1,5" 32 3898bc395a6SKent Gibson insmod_test "0,32,30,35" 32 3908bc395a6SKent Gibson insmod_test "0,32,31,32" 32 3918bc395a6SKent Gibson insmod_test "10,32,30,35" 22 3928bc395a6SKent Gibson insmod_test "10,32,9,14" 22 3938bc395a6SKent Gibson insmod_test "0,32,20,21,40,56" 32 16 3948bc395a6SKent Gibson insmod_test "0,32,32,64,32,40" 32 32 3958bc395a6SKent Gibson insmod_test "0,32,32,64,36,37" 32 32 3968bc395a6SKent Gibson insmod_test "0,32,35,64,34,36" 32 29 3978bc395a6SKent Gibson insmod_test "0,30,35,64,35,45" 30 29 3988bc395a6SKent Gibson insmod_test "0,32,40,56,30,33" 32 16 3998bc395a6SKent Gibson insmod_test "0,32,40,56,30,41" 32 16 4008bc395a6SKent Gibson insmod_test "0,32,40,56,39,45" 32 16 40122f6592bSBamvor Jian Zhangfi 40222f6592bSBamvor Jian Zhang 4038bc395a6SKent Gibsonecho "GPIO $module test PASS" 404