I am hoping that you can provide advice on using UIO to handle an interrupt from user space. I found an excellent summary at https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html and have tried to follow it as well as I can, being a newcomer to Yocto and embedded Linux.
We are using a Variscite DART-MX8M-MINI development kit. I have enabled spidev, which I am using to communicate with an ADS1299 EEG analog front end from TI. It generates a “data ready” interrupt DRDY# (active low). I’d like to be able to handle this falling-edge interrupt by connecting it to a GPIO (GPIO1_0) and either read() or poll() to wait for an interrupt, and can then read the acquired data using /dev/spidev0.0.
In my device tree, I have added the following under my &ecspi1 node. I am not certain this is the correct place to add this information, or if I can simply add it within the device tree “root” node “/ {“. I would appreciate your advice on the best place add this information.
// Added for DRDY# interrupt on GPIO1_0 from user space
user_io@0 {
compatible = "mydevice,generic-uio,ui_pdrv";
status = "okay";
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_user_io>;
};
Under my dts &iomuxc node, the various pinctrl groups are defined. I added the following for GPIO1_0:
// Added for DRDY# interrupt on GPIO1_0 from user space
pinctrl_user_io: user_io-0 {
fsl,pins = <
MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x1c0
>;
};
This _should_ configure the pin to enable a pull-up. Can you confirm this?
I have modified my kernel .config file via menuconfig, and it contains the following entries:
CONFIG_UIO=y
CONFIG_UIO_PDRV_GENIRQ=m
The “y” setting for CONFIG_UIO was evidently due to other dependencies in the provided configuration.
However, when I boot the board up, I cannot see /dev/uio0 or run the modprobe command as specified in the description at the link provided:
root@imx8mm-var-dart:~# ls /dev/u*
/dev/ubi_ctrl /dev/udev_network_queue /dev/uhid /dev/uinput /dev/urandom
root@imx8mm-var-dart:~# modprobe uio_pdrv_genirq of_id="mydevice,generic-uio,ui_pdrv"
modprobe: FATAL: Module uio_pdrv_genirq not found in directory /lib/modules/4.19.35-imx8mm+ge6d3e3fefe4e
I used grep to look for “uio” in the /lib/modules directory, and only found the following:
root@imx8mm-var-dart:/lib/modules/4.19.35-imx8mm+ge6d3e3fefe4e# grep -RnI uio .
./modules.builtin:270:kernel/drivers/uio/uio.ko
I am stumped, and think I must have something wrong in my .dts file, my .config file, or in the packages/libraries added to the Yocto image. Do you have any suggestions for how to diagnose/fix this problem. My .dts file and .config file is attached.
Thanks for your help. UIO apparently is a "preferred" way to handle writing simple device drivers from user space. Do I need to add something to Yocto to enable UIO and UIO_PDRV_GENIRQ?
Best regards,
Scott
Hello,
You can see if the Interrupt it is already set, by using CAT like this :
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
16: 2313 1658 2361 878 GIC 29 twd
17: 0 0 0 0 GIC 87 i.MX Timer Tick
18: 35 0 0 0 GIC 45 mxs-dma
19: 5 0 0 0 GIC 47 bch
22: 2 0 0 0 GIC 65 2010000.ecspi
23: 0 0 0 0 GIC 79 202c000.ssi
38: 0 0 0 0 gpio-mxc 6 2198000.usdhc cd
75: 69 0 0 0 gpio-mxc 9 da9063-irq
147: 6 0 0 0 gpio-mxc 13 PS_irq_handler
150: 193 0 0 0 gpio-mxc 16 CLK_irq_handler
And you can apply to linux documentation, like:
Thanks for your reply. My gpio1_0 line does not seem to appear in cat /proc/interrupts:
root@imx8mm-var-dart:~# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
3: 6583 6523 6361 6633 GICv3 30 Level arch_timer
6: 40 81 99 39 GICv3 79 Level iMX system counter timer
7: 0 0 0 0 GICv3 23 Level arm-pmu
8: 0 0 0 0 GICv3 106 Level ddrc
9: 0 0 0 0 GICv3 107 Level ddrc
10: 0 0 0 0 GICv3 108 Level ddrc
11: 0 0 0 0 GICv3 109 Level ddrc
12: 0 0 0 0 GICv3 130 Edge ddr_perf
13: 0 0 0 0 GICv3 48 Level csi
14: 0 0 0 0 GICv3 49 Level 32e30000.mipi_csi
25: 0 0 0 0 GICv3 36 Level 30370000.snvs:snvs-powerkey
28: 563 0 0 0 GICv3 58 Level 30860000.serial
29: 0 0 0 0 GICv3 60 Level 30880000.serial
30: 0 0 0 0 GICv3 59 Level 30890000.serial
31: 541 0 0 0 GICv3 67 Level 30a20000.i2c
32: 148 0 0 0 GICv3 68 Level 30a30000.i2c
33: 62 0 0 0 GICv3 69 Level 30a40000.i2c
34: 0 0 0 0 GICv3 70 Level 30a50000.i2c
35: 5 0 0 0 GICv3 61 Level 30a60000.serial
37: 0 0 0 0 GICv3 72 Level 32e40000.usb
38: 79 0 0 0 GICv3 73 Level 32e50000.usb
39: 11021 0 0 0 GICv3 54 Level mmc0
40: 4439 0 0 0 GICv3 55 Level mmc1
41: 536 0 0 0 GICv3 56 Level mmc2
42: 0 0 0 0 GICv3 82 Level sai
43: 768 0 0 0 GICv3 34 Level sdma
44: 0 0 0 0 GICv3 135 Level sdma
45: 0 0 0 0 GICv3 66 Level sdma
46: 0 0 0 0 GICv3 110 Level 30280000.wdog
47: 0 0 0 0 GICv3 63 Level 30820000.ecspi
48: 1 0 0 0 GICv3 150 Level 30be0000.ethernet
49: 0 0 0 0 GICv3 151 Level 30be0000.ethernet
50: 196 0 0 0 GICv3 152 Level 30be0000.ethernet
51: 839 0 0 0 GICv3 37 Level imx-lcdif-crtc.0
52: 1 0 0 0 GICv3 50 Level 32e10000.mipi_dsi
56: 0 0 0 0 GICv3 62 Level hx280enc
57: 0 0 0 0 GICv3 39 Level hantrodec
58: 0 0 0 0 GICv3 40 Level hantrodec
59: 127 0 0 0 GICv3 35 Level galcore:0
60: 66 0 0 0 GICv3 57 Level galcore:2d
62: 0 0 0 0 GICv3 52 Level caam-snvs
78: 0 0 0 0 gpio-mxc 14 Edge edt-ft5x06
79: 0 0 0 0 gpio-mxc 15 Edge ds1337
104: 0 0 0 0 gpio-mxc 8 Edge bd718xx-irq
108: 0 0 0 0 gpio-mxc 12 Edge 30b50000.mmc cd
166: 0 0 0 0 gpio-mxc 6 Edge Back
173: 0 0 0 0 gpio-mxc 13 Edge Home
175: 0 0 0 0 gpio-mxc 15 Edge Down
178: 0 0 0 0 gpio-mxc 18 Edge Up
224: 0 0 0 0 bd718xx-irq 5 Edge gpio_keys
225: 2 0 0 0 GICv3 137 Level 30901000.jr0
226: 4 0 0 0 GICv3 138 Level 30902000.jr1
227: 0 0 0 0 GICv3 146 Level 30903000.jr2
IPI0: 1470 13013 2654 2594 Rescheduling interrupts
IPI1: 74 165 163 164 Function call interrupts
IPI2: 0 0 0 0 CPU stop interrupts
IPI3: 0 0 0 0 CPU stop (for crash dump) interrupts
IPI4: 3 14 28 27 Timer broadcast interrupts
IPI5: 1040 276 307 383 IRQ work interrupts
IPI6: 0 0 0 0 CPU wake-up interrupts
Err: 0
root@imx8mm-var-dart:~#
The first link you provided brought me to a generic page on makelinux.net. Perhaps it was incorrect?
The second link brought me to a general description of Linux interrupt handlers, but I'm trying to use UIO so that I can handle a GPIO interrupt from user space, not write a Linux kernel module.
Can you provide any help regarding enabling UIO and the UIO interrupt handling?
Many thanks!
Scott