162306a36Sopenharmony_ci#!/bin/bash -efu
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#exit status
562306a36Sopenharmony_ci#0: success
662306a36Sopenharmony_ci#1: fail
762306a36Sopenharmony_ci#4: skip test - including run as non-root user
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciBASE=${0%/*}
1062306a36Sopenharmony_ciDEBUGFS=
1162306a36Sopenharmony_ciGPIO_DEBUGFS=
1262306a36Sopenharmony_cidev_type="cdev"
1362306a36Sopenharmony_cimodule="gpio-mockup"
1462306a36Sopenharmony_civerbose=
1562306a36Sopenharmony_cifull_test=
1662306a36Sopenharmony_cirandom=
1762306a36Sopenharmony_ciuapi_opt=
1862306a36Sopenharmony_ciactive_opt=
1962306a36Sopenharmony_cibias_opt=
2062306a36Sopenharmony_ciline_set_pid=
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci# Kselftest return codes
2362306a36Sopenharmony_ciksft_fail=1
2462306a36Sopenharmony_ciksft_skip=4
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciusage()
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	echo "Usage:"
2962306a36Sopenharmony_ci	echo "$0 [-frv] [-t type]"
3062306a36Sopenharmony_ci	echo "-f:  full test (minimal set run by default)"
3162306a36Sopenharmony_ci	echo "-r:  test random lines as well as fence posts"
3262306a36Sopenharmony_ci	echo "-t:  interface type:"
3362306a36Sopenharmony_ci	echo "      cdev (character device ABI) - default"
3462306a36Sopenharmony_ci	echo "      cdev_v1 (deprecated character device ABI)"
3562306a36Sopenharmony_ci	echo "      sysfs (deprecated SYSFS ABI)"
3662306a36Sopenharmony_ci	echo "-v:  verbose progress reporting"
3762306a36Sopenharmony_ci	exit $ksft_fail
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ciskip()
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	echo "$*" >&2
4362306a36Sopenharmony_ci	echo "GPIO $module test SKIP"
4462306a36Sopenharmony_ci	exit $ksft_skip
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciprerequisite()
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	[ $(id -u) -eq 0 ] || skip "must be run as root"
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	DEBUGFS=$(grep -w debugfs /proc/mounts | cut -f2 -d' ')
5262306a36Sopenharmony_ci	[ -d "$DEBUGFS" ] || skip "debugfs is not mounted"
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	GPIO_DEBUGFS=$DEBUGFS/$module
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciremove_module()
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	modprobe -r -q $module
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cicleanup()
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	set +e
6562306a36Sopenharmony_ci	release_line
6662306a36Sopenharmony_ci	remove_module
6762306a36Sopenharmony_ci	jobs -p | xargs -r kill > /dev/null 2>&1
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cifail()
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	echo "test failed: $*" >&2
7362306a36Sopenharmony_ci	echo "GPIO $module test FAIL"
7462306a36Sopenharmony_ci	exit $ksft_fail
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_citry_insert_module()
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	modprobe -q $module "$1" || fail "insert $module failed with error $?"
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cilog()
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	[ -z "$verbose" ] || echo "$*"
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci# The following line helpers, release_Line, get_line and set_line, all
8862306a36Sopenharmony_ci# make use of the global $chip and $offset variables.
8962306a36Sopenharmony_ci#
9062306a36Sopenharmony_ci# This implementation drives the GPIO character device (cdev) uAPI.
9162306a36Sopenharmony_ci# Other implementations may override these to test different uAPIs.
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci# Release any resources related to the line
9462306a36Sopenharmony_cirelease_line()
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	[ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true
9762306a36Sopenharmony_ci	line_set_pid=
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci# Read the current value of the line
10162306a36Sopenharmony_ciget_line()
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	release_line
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	local cdev_opts=${uapi_opt}${active_opt}
10662306a36Sopenharmony_ci	$BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset
10762306a36Sopenharmony_ci	echo $?
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci# Set the state of the line
11162306a36Sopenharmony_ci#
11262306a36Sopenharmony_ci# Changes to line configuration are provided as parameters.
11362306a36Sopenharmony_ci# The line is assumed to be an output if the line value 0 or 1 is
11462306a36Sopenharmony_ci# specified, else an input.
11562306a36Sopenharmony_ciset_line()
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	local val=
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	release_line
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	# parse config options...
12262306a36Sopenharmony_ci	for option in $*; do
12362306a36Sopenharmony_ci		case $option in
12462306a36Sopenharmony_ci		active-low)
12562306a36Sopenharmony_ci			active_opt="-l "
12662306a36Sopenharmony_ci			;;
12762306a36Sopenharmony_ci		active-high)
12862306a36Sopenharmony_ci			active_opt=
12962306a36Sopenharmony_ci			;;
13062306a36Sopenharmony_ci		bias-none)
13162306a36Sopenharmony_ci			bias_opt=
13262306a36Sopenharmony_ci			;;
13362306a36Sopenharmony_ci		pull-down)
13462306a36Sopenharmony_ci			bias_opt="-bpull-down "
13562306a36Sopenharmony_ci			;;
13662306a36Sopenharmony_ci		pull-up)
13762306a36Sopenharmony_ci			bias_opt="-bpull-up "
13862306a36Sopenharmony_ci			;;
13962306a36Sopenharmony_ci		0)
14062306a36Sopenharmony_ci			val=0
14162306a36Sopenharmony_ci			;;
14262306a36Sopenharmony_ci		1)
14362306a36Sopenharmony_ci			val=1
14462306a36Sopenharmony_ci			;;
14562306a36Sopenharmony_ci		esac
14662306a36Sopenharmony_ci	done
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	local cdev_opts=${uapi_opt}${active_opt}
14962306a36Sopenharmony_ci	if [ "$val" ]; then
15062306a36Sopenharmony_ci		$BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset &
15162306a36Sopenharmony_ci		# failure to set is detected by reading mockup and toggling values
15262306a36Sopenharmony_ci		line_set_pid=$!
15362306a36Sopenharmony_ci		# allow for gpio-mockup-cdev to launch and request line
15462306a36Sopenharmony_ci		# (there is limited value in checking if line has been requested)
15562306a36Sopenharmony_ci		sleep 0.01
15662306a36Sopenharmony_ci	elif [ "$bias_opt" ]; then
15762306a36Sopenharmony_ci		cdev_opts=${cdev_opts}${bias_opt}
15862306a36Sopenharmony_ci		$BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true
15962306a36Sopenharmony_ci	fi
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciassert_line()
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	local val
16562306a36Sopenharmony_ci	# don't need any retry here as set_mock allows for propagation
16662306a36Sopenharmony_ci	val=$(get_line)
16762306a36Sopenharmony_ci	[ "$val" = "$1" ] || fail "line value is ${val:-empty} when $1 was expected"
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci# The following mockup helpers all make use of the $mock_line
17162306a36Sopenharmony_ciassert_mock()
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	local backoff_wait=10
17462306a36Sopenharmony_ci	local retry=0
17562306a36Sopenharmony_ci	local val
17662306a36Sopenharmony_ci	# retry allows for set propagation from uAPI to mockup
17762306a36Sopenharmony_ci	while true; do
17862306a36Sopenharmony_ci		val=$(< $mock_line)
17962306a36Sopenharmony_ci		[ "$val" = "$1" ] && break
18062306a36Sopenharmony_ci		retry=$((retry + 1))
18162306a36Sopenharmony_ci		[ $retry -lt 5 ] || fail "mockup $mock_line value ${val:-empty} when $1 expected"
18262306a36Sopenharmony_ci		sleep $(printf "%0.2f" $((backoff_wait))e-3)
18362306a36Sopenharmony_ci		backoff_wait=$((backoff_wait * 2))
18462306a36Sopenharmony_ci	done
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ciset_mock()
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	echo "$1" > $mock_line
19062306a36Sopenharmony_ci	# allow for set propagation - so we won't be in a race with set_line
19162306a36Sopenharmony_ci	assert_mock "$1"
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci# test the functionality of a line
19562306a36Sopenharmony_ci#
19662306a36Sopenharmony_ci# The line is set from the mockup side and is read from the userspace side
19762306a36Sopenharmony_ci# (input), and is set from the userspace side and is read from the mockup side
19862306a36Sopenharmony_ci# (output).
19962306a36Sopenharmony_ci#
20062306a36Sopenharmony_ci# Setting the mockup pull using the userspace interface bias settings is
20162306a36Sopenharmony_ci# tested where supported by the userspace interface (cdev).
20262306a36Sopenharmony_citest_line()
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	chip=$1
20562306a36Sopenharmony_ci	offset=$2
20662306a36Sopenharmony_ci	log "test_line $chip $offset"
20762306a36Sopenharmony_ci	mock_line=$GPIO_DEBUGFS/$chip/$offset
20862306a36Sopenharmony_ci	[ -e "$mock_line" ] || fail "missing line $chip:$offset"
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	# test input active-high
21162306a36Sopenharmony_ci	set_mock 1
21262306a36Sopenharmony_ci	set_line input active-high
21362306a36Sopenharmony_ci	assert_line 1
21462306a36Sopenharmony_ci	set_mock 0
21562306a36Sopenharmony_ci	assert_line 0
21662306a36Sopenharmony_ci	set_mock 1
21762306a36Sopenharmony_ci	assert_line 1
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	if [ "$full_test" ]; then
22062306a36Sopenharmony_ci		if [ "$dev_type" != "sysfs" ]; then
22162306a36Sopenharmony_ci			# test pulls
22262306a36Sopenharmony_ci			set_mock 0
22362306a36Sopenharmony_ci			set_line input pull-up
22462306a36Sopenharmony_ci			assert_line 1
22562306a36Sopenharmony_ci			set_mock 0
22662306a36Sopenharmony_ci			assert_line 0
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci			set_mock 1
22962306a36Sopenharmony_ci			set_line input pull-down
23062306a36Sopenharmony_ci			assert_line 0
23162306a36Sopenharmony_ci			set_mock 1
23262306a36Sopenharmony_ci			assert_line 1
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci			set_line bias-none
23562306a36Sopenharmony_ci		fi
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci		# test input active-low
23862306a36Sopenharmony_ci		set_mock 0
23962306a36Sopenharmony_ci		set_line active-low
24062306a36Sopenharmony_ci		assert_line 1
24162306a36Sopenharmony_ci		set_mock 1
24262306a36Sopenharmony_ci		assert_line 0
24362306a36Sopenharmony_ci		set_mock 0
24462306a36Sopenharmony_ci		assert_line 1
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		# test output active-high
24762306a36Sopenharmony_ci		set_mock 1
24862306a36Sopenharmony_ci		set_line active-high 0
24962306a36Sopenharmony_ci		assert_mock 0
25062306a36Sopenharmony_ci		set_line 1
25162306a36Sopenharmony_ci		assert_mock 1
25262306a36Sopenharmony_ci		set_line 0
25362306a36Sopenharmony_ci		assert_mock 0
25462306a36Sopenharmony_ci	fi
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	# test output active-low
25762306a36Sopenharmony_ci	set_mock 0
25862306a36Sopenharmony_ci	set_line active-low 0
25962306a36Sopenharmony_ci	assert_mock 1
26062306a36Sopenharmony_ci	set_line 1
26162306a36Sopenharmony_ci	assert_mock 0
26262306a36Sopenharmony_ci	set_line 0
26362306a36Sopenharmony_ci	assert_mock 1
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	release_line
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_citest_no_line()
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	log test_no_line "$*"
27162306a36Sopenharmony_ci	[ ! -e "$GPIO_DEBUGFS/$1/$2" ] || fail "unexpected line $1:$2"
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci# Load the module and check that the expected number of gpiochips, with the
27562306a36Sopenharmony_ci# expected number of lines, are created and are functional.
27662306a36Sopenharmony_ci#
27762306a36Sopenharmony_ci# $1 is the gpio_mockup_ranges parameter for the module
27862306a36Sopenharmony_ci# The remaining parameters are the number of lines, n, expected for each of
27962306a36Sopenharmony_ci# the gpiochips expected to be created.
28062306a36Sopenharmony_ci#
28162306a36Sopenharmony_ci# For each gpiochip the fence post lines, 0 and n-1, are tested, and the
28262306a36Sopenharmony_ci# line on the far side of the fence post, n, is tested to not exist.
28362306a36Sopenharmony_ci#
28462306a36Sopenharmony_ci# If the $random flag is set then a random line in the middle of the
28562306a36Sopenharmony_ci# gpiochip is tested as well.
28662306a36Sopenharmony_ciinsmod_test()
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	local ranges=
28962306a36Sopenharmony_ci	local gc=
29062306a36Sopenharmony_ci	local width=
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	[ "${1:-}" ] || fail "missing ranges"
29362306a36Sopenharmony_ci	ranges=$1 ; shift
29462306a36Sopenharmony_ci	try_insert_module "gpio_mockup_ranges=$ranges"
29562306a36Sopenharmony_ci	log "GPIO $module test with ranges: <$ranges>:"
29662306a36Sopenharmony_ci	# e.g. /sys/kernel/debug/gpio-mockup/gpiochip1
29762306a36Sopenharmony_ci	gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort)
29862306a36Sopenharmony_ci	for chip in $gpiochip; do
29962306a36Sopenharmony_ci		gc=${chip##*/}
30062306a36Sopenharmony_ci		[ "${1:-}" ] || fail "unexpected chip - $gc"
30162306a36Sopenharmony_ci		width=$1 ; shift
30262306a36Sopenharmony_ci		test_line $gc 0
30362306a36Sopenharmony_ci		if [ "$random" -a $width -gt 2 ]; then
30462306a36Sopenharmony_ci			test_line $gc $((RANDOM % ($width - 2) + 1))
30562306a36Sopenharmony_ci		fi
30662306a36Sopenharmony_ci		test_line $gc $(($width - 1))
30762306a36Sopenharmony_ci		test_no_line $gc $width
30862306a36Sopenharmony_ci	done
30962306a36Sopenharmony_ci	[ "${1:-}" ] && fail "missing expected chip of width $1"
31062306a36Sopenharmony_ci	remove_module || fail "failed to remove module with error $?"
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ciwhile getopts ":frvt:" opt; do
31462306a36Sopenharmony_ci	case $opt in
31562306a36Sopenharmony_ci	f)
31662306a36Sopenharmony_ci		full_test=true
31762306a36Sopenharmony_ci		;;
31862306a36Sopenharmony_ci	r)
31962306a36Sopenharmony_ci		random=true
32062306a36Sopenharmony_ci		;;
32162306a36Sopenharmony_ci	t)
32262306a36Sopenharmony_ci		dev_type=$OPTARG
32362306a36Sopenharmony_ci		;;
32462306a36Sopenharmony_ci	v)
32562306a36Sopenharmony_ci		verbose=true
32662306a36Sopenharmony_ci		;;
32762306a36Sopenharmony_ci	*)
32862306a36Sopenharmony_ci		usage
32962306a36Sopenharmony_ci		;;
33062306a36Sopenharmony_ci	esac
33162306a36Sopenharmony_cidone
33262306a36Sopenharmony_cishift $((OPTIND - 1))
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci[ "${1:-}" ] && fail "unknown argument '$1'"
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ciprerequisite
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_citrap 'exit $ksft_fail' SIGTERM SIGINT
33962306a36Sopenharmony_citrap cleanup EXIT
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_cicase "$dev_type" in
34262306a36Sopenharmony_cisysfs)
34362306a36Sopenharmony_ci	source $BASE/gpio-mockup-sysfs.sh
34462306a36Sopenharmony_ci	echo "WARNING: gpio sysfs ABI is deprecated."
34562306a36Sopenharmony_ci	;;
34662306a36Sopenharmony_cicdev_v1)
34762306a36Sopenharmony_ci	echo "WARNING: gpio cdev ABI v1 is deprecated."
34862306a36Sopenharmony_ci	uapi_opt="-u1 "
34962306a36Sopenharmony_ci	;;
35062306a36Sopenharmony_cicdev)
35162306a36Sopenharmony_ci	;;
35262306a36Sopenharmony_ci*)
35362306a36Sopenharmony_ci	fail "unknown interface type: $dev_type"
35462306a36Sopenharmony_ci	;;
35562306a36Sopenharmony_ciesac
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ciremove_module || fail "can't remove existing $module module"
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci# manual gpio allocation tests fail if a physical chip already exists
36062306a36Sopenharmony_ci[ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0"
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ciecho "1.  Module load tests"
36362306a36Sopenharmony_ciecho "1.1.  dynamic allocation of gpio"
36462306a36Sopenharmony_ciinsmod_test "-1,32" 32
36562306a36Sopenharmony_ciinsmod_test "-1,23,-1,32" 23 32
36662306a36Sopenharmony_ciinsmod_test "-1,23,-1,26,-1,32" 23 26 32
36762306a36Sopenharmony_ciif [ "$full_test" ]; then
36862306a36Sopenharmony_ci	echo "1.2.  manual allocation of gpio"
36962306a36Sopenharmony_ci	insmod_test "0,32" 32
37062306a36Sopenharmony_ci	insmod_test "0,32,32,60" 32 28
37162306a36Sopenharmony_ci	insmod_test "0,32,40,64,64,96" 32 24 32
37262306a36Sopenharmony_ci	echo "1.3.  dynamic and manual allocation of gpio"
37362306a36Sopenharmony_ci	insmod_test "-1,32,32,62" 32 30
37462306a36Sopenharmony_ci	insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32
37562306a36Sopenharmony_ci	insmod_test "-1,32,32,60,-1,29" 32 28 29
37662306a36Sopenharmony_ci	insmod_test "-1,32,40,64,-1,5" 32 24 5
37762306a36Sopenharmony_ci	insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31
37862306a36Sopenharmony_cifi
37962306a36Sopenharmony_ciecho "2.  Module load error tests"
38062306a36Sopenharmony_ciecho "2.1 gpio overflow"
38162306a36Sopenharmony_ci# Currently: The max number of gpio(1024) is defined in arm architecture.
38262306a36Sopenharmony_ciinsmod_test "-1,1024"
38362306a36Sopenharmony_ciif [ "$full_test" ]; then
38462306a36Sopenharmony_ci	echo "2.2 no lines defined"
38562306a36Sopenharmony_ci	insmod_test "0,0"
38662306a36Sopenharmony_ci	echo "2.3 ignore range overlap"
38762306a36Sopenharmony_ci	insmod_test "0,32,0,1" 32
38862306a36Sopenharmony_ci	insmod_test "0,32,1,5" 32
38962306a36Sopenharmony_ci	insmod_test "0,32,30,35" 32
39062306a36Sopenharmony_ci	insmod_test "0,32,31,32" 32
39162306a36Sopenharmony_ci	insmod_test "10,32,30,35" 22
39262306a36Sopenharmony_ci	insmod_test "10,32,9,14" 22
39362306a36Sopenharmony_ci	insmod_test "0,32,20,21,40,56" 32 16
39462306a36Sopenharmony_ci	insmod_test "0,32,32,64,32,40" 32 32
39562306a36Sopenharmony_ci	insmod_test "0,32,32,64,36,37" 32 32
39662306a36Sopenharmony_ci	insmod_test "0,32,35,64,34,36" 32 29
39762306a36Sopenharmony_ci	insmod_test "0,30,35,64,35,45" 30 29
39862306a36Sopenharmony_ci	insmod_test "0,32,40,56,30,33" 32 16
39962306a36Sopenharmony_ci	insmod_test "0,32,40,56,30,41" 32 16
40062306a36Sopenharmony_ci	insmod_test "0,32,40,56,39,45" 32 16
40162306a36Sopenharmony_cifi
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ciecho "GPIO $module test PASS"
404