gpio-sim.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #!/bin/sh
  2. # SPDX-License-Identifier: GPL-2.0
  3. # Copyright (C) 2021 Bartosz Golaszewski <brgl@bgdev.pl>
  4. BASE_DIR=`dirname $0`
  5. CONFIGFS_DIR="/sys/kernel/config/gpio-sim"
  6. MODULE="gpio-sim"
  7. fail() {
  8. echo "$*" >&2
  9. echo "GPIO $MODULE test FAIL"
  10. exit 1
  11. }
  12. skip() {
  13. echo "$*" >&2
  14. echo "GPIO $MODULE test SKIP"
  15. exit 4
  16. }
  17. remove_chip() {
  18. local CHIP=$1
  19. for FILE in $CONFIGFS_DIR/$CHIP/*; do
  20. BANK=`basename $FILE`
  21. if [ "$BANK" = "live" -o "$BANK" = "dev_name" ]; then
  22. continue
  23. fi
  24. LINES=`ls $CONFIGFS_DIR/$CHIP/$BANK/ | grep -E ^line`
  25. if [ "$?" = 0 ]; then
  26. for LINE in $LINES; do
  27. if [ -e $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog ]; then
  28. rmdir $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog || \
  29. fail "Unable to remove the hog"
  30. fi
  31. rmdir $CONFIGFS_DIR/$CHIP/$BANK/$LINE || \
  32. fail "Unable to remove the line"
  33. done
  34. fi
  35. rmdir $CONFIGFS_DIR/$CHIP/$BANK
  36. done
  37. rmdir $CONFIGFS_DIR/$CHIP || fail "Unable to remove the chip"
  38. }
  39. create_chip() {
  40. local CHIP=$1
  41. mkdir $CONFIGFS_DIR/$CHIP
  42. }
  43. create_bank() {
  44. local CHIP=$1
  45. local BANK=$2
  46. mkdir $CONFIGFS_DIR/$CHIP/$BANK
  47. }
  48. set_label() {
  49. local CHIP=$1
  50. local BANK=$2
  51. local LABEL=$3
  52. echo $LABEL > $CONFIGFS_DIR/$CHIP/$BANK/label || fail "Unable to set the chip label"
  53. }
  54. set_num_lines() {
  55. local CHIP=$1
  56. local BANK=$2
  57. local NUM_LINES=$3
  58. echo $NUM_LINES > $CONFIGFS_DIR/$CHIP/$BANK/num_lines || \
  59. fail "Unable to set the number of lines"
  60. }
  61. set_line_name() {
  62. local CHIP=$1
  63. local BANK=$2
  64. local OFFSET=$3
  65. local NAME=$4
  66. local LINE_DIR=$CONFIGFS_DIR/$CHIP/$BANK/line$OFFSET
  67. test -d $LINE_DIR || mkdir $LINE_DIR
  68. echo $NAME > $LINE_DIR/name || fail "Unable to set the line name"
  69. }
  70. enable_chip() {
  71. local CHIP=$1
  72. echo 1 > $CONFIGFS_DIR/$CHIP/live || fail "Unable to enable the chip"
  73. }
  74. disable_chip() {
  75. local CHIP=$1
  76. echo 0 > $CONFIGFS_DIR/$CHIP/live || fail "Unable to disable the chip"
  77. }
  78. configfs_cleanup() {
  79. for CHIP in `ls $CONFIGFS_DIR/`; do
  80. disable_chip $CHIP
  81. remove_chip $CHIP
  82. done
  83. }
  84. configfs_chip_name() {
  85. local CHIP=$1
  86. local BANK=$2
  87. cat $CONFIGFS_DIR/$CHIP/$BANK/chip_name 2> /dev/null || \
  88. fail "unable to read the chip name from configfs"
  89. }
  90. configfs_dev_name() {
  91. local CHIP=$1
  92. cat $CONFIGFS_DIR/$CHIP/dev_name 2> /dev/null || \
  93. fail "unable to read the device name from configfs"
  94. }
  95. get_chip_num_lines() {
  96. local CHIP=$1
  97. local BANK=$2
  98. $BASE_DIR/gpio-chip-info /dev/`configfs_chip_name $CHIP $BANK` num-lines || \
  99. fail "unable to read the number of lines from the character device"
  100. }
  101. get_chip_label() {
  102. local CHIP=$1
  103. local BANK=$2
  104. $BASE_DIR/gpio-chip-info /dev/`configfs_chip_name $CHIP $BANK` label || \
  105. fail "unable to read the chip label from the character device"
  106. }
  107. get_line_name() {
  108. local CHIP=$1
  109. local BANK=$2
  110. local OFFSET=$3
  111. $BASE_DIR/gpio-line-name /dev/`configfs_chip_name $CHIP $BANK` $OFFSET || \
  112. fail "unable to read the line name from the character device"
  113. }
  114. sysfs_set_pull() {
  115. local DEV=$1
  116. local BANK=$2
  117. local OFFSET=$3
  118. local PULL=$4
  119. local DEVNAME=`configfs_dev_name $DEV`
  120. local CHIPNAME=`configfs_chip_name $DEV $BANK`
  121. local SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio$OFFSET/pull"
  122. echo $PULL > $SYSFS_PATH || fail "Unable to set line pull in sysfs"
  123. }
  124. # Load the gpio-sim module. This will pull in configfs if needed too.
  125. modprobe gpio-sim || skip "unable to load the gpio-sim module"
  126. # Make sure configfs is mounted at /sys/kernel/config. Wait a bit if needed.
  127. for IDX in `seq 5`; do
  128. if [ "$IDX" -eq "5" ]; then
  129. skip "configfs not mounted at /sys/kernel/config"
  130. fi
  131. mountpoint -q /sys/kernel/config && break
  132. sleep 0.1
  133. done
  134. # If the module was already loaded: remove all previous chips
  135. configfs_cleanup
  136. trap "exit 1" SIGTERM SIGINT
  137. trap configfs_cleanup EXIT
  138. echo "1. chip_name and dev_name attributes"
  139. echo "1.1. Chip name is communicated to user"
  140. create_chip chip
  141. create_bank chip bank
  142. enable_chip chip
  143. test -n `cat $CONFIGFS_DIR/chip/bank/chip_name` || fail "chip_name doesn't work"
  144. disable_chip chip
  145. remove_chip chip
  146. echo "1.2. chip_name returns 'none' if the chip is still pending"
  147. create_chip chip
  148. create_bank chip bank
  149. test "`cat $CONFIGFS_DIR/chip/bank/chip_name`" = "none" || \
  150. fail "chip_name doesn't return 'none' for a pending chip"
  151. remove_chip chip
  152. echo "1.3. Device name is communicated to user"
  153. create_chip chip
  154. create_bank chip bank
  155. enable_chip chip
  156. test -n `cat $CONFIGFS_DIR/chip/dev_name` || fail "dev_name doesn't work"
  157. disable_chip chip
  158. remove_chip chip
  159. echo "2. Creating and configuring simulated chips"
  160. echo "2.1. Default number of lines is 1"
  161. create_chip chip
  162. create_bank chip bank
  163. enable_chip chip
  164. test "`get_chip_num_lines chip bank`" = "1" || fail "default number of lines is not 1"
  165. disable_chip chip
  166. remove_chip chip
  167. echo "2.2. Number of lines can be specified"
  168. create_chip chip
  169. create_bank chip bank
  170. set_num_lines chip bank 16
  171. enable_chip chip
  172. test "`get_chip_num_lines chip bank`" = "16" || fail "number of lines is not 16"
  173. disable_chip chip
  174. remove_chip chip
  175. echo "2.3. Label can be set"
  176. create_chip chip
  177. create_bank chip bank
  178. set_label chip bank foobar
  179. enable_chip chip
  180. test "`get_chip_label chip bank`" = "foobar" || fail "label is incorrect"
  181. disable_chip chip
  182. remove_chip chip
  183. echo "2.4. Label can be left empty"
  184. create_chip chip
  185. create_bank chip bank
  186. enable_chip chip
  187. test -z "`cat $CONFIGFS_DIR/chip/bank/label`" || fail "label is not empty"
  188. disable_chip chip
  189. remove_chip chip
  190. echo "2.5. Line names can be configured"
  191. create_chip chip
  192. create_bank chip bank
  193. set_num_lines chip bank 16
  194. set_line_name chip bank 0 foo
  195. set_line_name chip bank 2 bar
  196. enable_chip chip
  197. test "`get_line_name chip bank 0`" = "foo" || fail "line name is incorrect"
  198. test "`get_line_name chip bank 2`" = "bar" || fail "line name is incorrect"
  199. disable_chip chip
  200. remove_chip chip
  201. echo "2.6. Line config can remain unused if offset is greater than number of lines"
  202. create_chip chip
  203. create_bank chip bank
  204. set_num_lines chip bank 2
  205. set_line_name chip bank 5 foobar
  206. enable_chip chip
  207. test "`get_line_name chip bank 0`" = "" || fail "line name is incorrect"
  208. test "`get_line_name chip bank 1`" = "" || fail "line name is incorrect"
  209. disable_chip chip
  210. remove_chip chip
  211. echo "2.7. Line configfs directory names are sanitized"
  212. create_chip chip
  213. create_bank chip bank
  214. mkdir $CONFIGFS_DIR/chip/bank/line12foobar 2> /dev/null && \
  215. fail "invalid configfs line name accepted"
  216. mkdir $CONFIGFS_DIR/chip/bank/line_no_offset 2> /dev/null && \
  217. fail "invalid configfs line name accepted"
  218. remove_chip chip
  219. echo "2.8. Multiple chips can be created"
  220. CHIPS="chip0 chip1 chip2"
  221. for CHIP in $CHIPS; do
  222. create_chip $CHIP
  223. create_bank $CHIP bank
  224. enable_chip $CHIP
  225. done
  226. for CHIP in $CHIPS; do
  227. disable_chip $CHIP
  228. remove_chip $CHIP
  229. done
  230. echo "2.9. Can't modify settings when chip is live"
  231. create_chip chip
  232. create_bank chip bank
  233. enable_chip chip
  234. echo foobar > $CONFIGFS_DIR/chip/bank/label 2> /dev/null && \
  235. fail "Setting label of a live chip should fail"
  236. echo 8 > $CONFIGFS_DIR/chip/bank/num_lines 2> /dev/null && \
  237. fail "Setting number of lines of a live chip should fail"
  238. disable_chip chip
  239. remove_chip chip
  240. echo "2.10. Can't create line items when chip is live"
  241. create_chip chip
  242. create_bank chip bank
  243. enable_chip chip
  244. mkdir $CONFIGFS_DIR/chip/bank/line0 2> /dev/null && fail "Creating line item should fail"
  245. disable_chip chip
  246. remove_chip chip
  247. echo "2.11. Probe errors are propagated to user-space"
  248. create_chip chip
  249. create_bank chip bank
  250. set_num_lines chip bank 99999
  251. echo 1 > $CONFIGFS_DIR/chip/live 2> /dev/null && fail "Probe error was not propagated"
  252. remove_chip chip
  253. echo "2.12. Cannot enable a chip without any GPIO banks"
  254. create_chip chip
  255. echo 1 > $CONFIGFS_DIR/chip/live 2> /dev/null && fail "Chip enabled without any GPIO banks"
  256. remove_chip chip
  257. echo "2.13. Duplicate chip labels are not allowed"
  258. create_chip chip
  259. create_bank chip bank0
  260. set_label chip bank0 foobar
  261. create_bank chip bank1
  262. set_label chip bank1 foobar
  263. echo 1 > $CONFIGFS_DIR/chip/live 2> /dev/null && fail "Duplicate chip labels were not rejected"
  264. remove_chip chip
  265. echo "2.14. Lines can be hogged"
  266. create_chip chip
  267. create_bank chip bank
  268. set_num_lines chip bank 8
  269. mkdir -p $CONFIGFS_DIR/chip/bank/line4/hog
  270. enable_chip chip
  271. $BASE_DIR/gpio-mockup-cdev -s 1 /dev/`configfs_chip_name chip bank` 4 2> /dev/null && \
  272. fail "Setting the value of a hogged line shouldn't succeed"
  273. disable_chip chip
  274. remove_chip chip
  275. echo "3. Controlling simulated chips"
  276. echo "3.1. Pull can be set over sysfs"
  277. create_chip chip
  278. create_bank chip bank
  279. set_num_lines chip bank 8
  280. enable_chip chip
  281. sysfs_set_pull chip bank 0 pull-up
  282. $BASE_DIR/gpio-mockup-cdev /dev/`configfs_chip_name chip bank` 0
  283. test "$?" = "1" || fail "pull set incorrectly"
  284. sysfs_set_pull chip bank 0 pull-down
  285. $BASE_DIR/gpio-mockup-cdev /dev/`configfs_chip_name chip bank` 1
  286. test "$?" = "0" || fail "pull set incorrectly"
  287. disable_chip chip
  288. remove_chip chip
  289. echo "3.2. Pull can be read from sysfs"
  290. create_chip chip
  291. create_bank chip bank
  292. set_num_lines chip bank 8
  293. enable_chip chip
  294. DEVNAME=`configfs_dev_name chip`
  295. CHIPNAME=`configfs_chip_name chip bank`
  296. SYSFS_PATH=/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/pull
  297. test `cat $SYSFS_PATH` = "pull-down" || fail "reading the pull failed"
  298. sysfs_set_pull chip bank 0 pull-up
  299. test `cat $SYSFS_PATH` = "pull-up" || fail "reading the pull failed"
  300. disable_chip chip
  301. remove_chip chip
  302. echo "3.3. Incorrect input in sysfs is rejected"
  303. create_chip chip
  304. create_bank chip bank
  305. set_num_lines chip bank 8
  306. enable_chip chip
  307. DEVNAME=`configfs_dev_name chip`
  308. CHIPNAME=`configfs_chip_name chip bank`
  309. SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/pull"
  310. echo foobar > $SYSFS_PATH 2> /dev/null && fail "invalid input not detected"
  311. disable_chip chip
  312. remove_chip chip
  313. echo "3.4. Can't write to value"
  314. create_chip chip
  315. create_bank chip bank
  316. enable_chip chip
  317. DEVNAME=`configfs_dev_name chip`
  318. CHIPNAME=`configfs_chip_name chip bank`
  319. SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
  320. echo 1 > $SYSFS_PATH 2> /dev/null && fail "writing to 'value' succeeded unexpectedly"
  321. disable_chip chip
  322. remove_chip chip
  323. echo "4. Simulated GPIO chips are functional"
  324. echo "4.1. Values can be read from sysfs"
  325. create_chip chip
  326. create_bank chip bank
  327. set_num_lines chip bank 8
  328. enable_chip chip
  329. DEVNAME=`configfs_dev_name chip`
  330. CHIPNAME=`configfs_chip_name chip bank`
  331. SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
  332. test `cat $SYSFS_PATH` = "0" || fail "incorrect value read from sysfs"
  333. $BASE_DIR/gpio-mockup-cdev -s 1 /dev/`configfs_chip_name chip bank` 0 &
  334. sleep 0.1 # FIXME Any better way?
  335. test `cat $SYSFS_PATH` = "1" || fail "incorrect value read from sysfs"
  336. kill $!
  337. disable_chip chip
  338. remove_chip chip
  339. echo "4.2. Bias settings work correctly"
  340. create_chip chip
  341. create_bank chip bank
  342. set_num_lines chip bank 8
  343. enable_chip chip
  344. DEVNAME=`configfs_dev_name chip`
  345. CHIPNAME=`configfs_chip_name chip bank`
  346. SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
  347. $BASE_DIR/gpio-mockup-cdev -b pull-up /dev/`configfs_chip_name chip bank` 0
  348. test `cat $SYSFS_PATH` = "1" || fail "bias setting does not work"
  349. disable_chip chip
  350. remove_chip chip
  351. echo "GPIO $MODULE test PASS"