gpiomon: error waiting for events: Input/output error

I’m using an updated BeagleV-Fire device and trying to monitor an input pin for level transitions. The command line tools gpioset and gpioget can be used to write and read two interconnected pins, however gpiomon fails when trying to monitor a pin.

Note: The RaspberryPi gpiomon tool works, however all of the Pi GPIO ports are initialised as inputs, which may alleviate any initial ISR configuration issue.

Calling gpioinfo reports that the pins as unused, but are all outputs.

beagle@BeagleV:~$ gpioinfo gpiochip3
gpiochip3 - 21 lines:
<snip>
        line  10:      "P9_23"       unused  output  active-high
        line  11:      unnamed       unused  output  active-high
        line  12:      "P9_25"       unused  output  active-high
        line  13:      unnamed       unused  output  active-high
        line  14:      "P9_27"       unused   input  active-high
<snip>

Executing the gpiomon command generates an error:

beagle@BeagleV:~$ gpiomon -r gpiochip3 12
gpiomon: error waiting for events: Input/output error

And reports errors in the kernel log:

[25246.884515] gpio gpiochip3: (41200000.gpio): gpiochip_lock_as_irq: tried to flag a GPIO set as output for IRQ
[25246.894579] gpio gpiochip3: (41200000.gpio): unable to lock HW IRQ 12 for IRQ
[25246.901866] genirq: Failed to request resources for gpiomon (irq 67) on irqchip mpfs

I’ve tried a variety of different methods (gpioget and “C” gpiod_line_* functions) to pre-configure GPIO as an input prior to calling gpiomon, but without success. Additionally the C function gpiod_line_request_rising_edge_events() fails and generates the same errors.

I did find mention of previous Linux kernel issue regarding GPIO when the pin is pre-configured as an output [Linux-Kernel Archive: [PATCH v2] pinctrl: st: add irq_request/release_resources callbacks] but couldn’t determine if Beagles have a similar patch applied.

Current OS information:

The kernel was updated as per 24.04 instructions. The gateware was updated from the OS default version. The device tree was modified to support SPI [How to enable SPI on BeagleV®-Fire]

beagle@BeagleV:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.2 LTS
Release:        24.04
Codename:       noble
beagle@BeagleV:~$ uname -a
Linux BeagleV 6.1.33-linux4microchip+fpga-2023.06-20231121+ #1 SMP Tue Nov 21 13:43:17 UTC 2023 riscv64 riscv64 riscv64 GNU/Linux
beagle@BeagleV:~$ tree /proc/device-tree/chosen/overlays/
/proc/device-tree/chosen/overlays/
├── DEFAULT-CAPE-GATEWARE
├── PCIE-M2-GATEWARE
└── name

1 directory, 3 files
beagle@BeagleV:~$ cat /proc/device-tree/chosen/overlays/DEFAULT-CAPE-GATEWARE
0.5.1-25-g6ba5ed3
beagle@BeagleV:~$ sudo apt-get install gpiod
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
gpiod is already the newest version (1.6.3-1.1build1).

Well, the current images are being built using the CI here,
so feel free to go take a look for your patch…

Remember, we’re always happy to take a MR,
should you find that the patch you mention is required.

Please note: We’re on Kernel 6.6, so your problem might already be solved.

I was using v6.1.x-Beagle to be compatible with a stream of Linux used elsewhere, but have tried main with the following results:

> beagle@BeagleV:~$ uname -a
> Linux BeagleV 6.6.51-linux4microchip+fpga-2024.09-20250312+ #1 SMP Wed Mar 12 15:16:08 UTC 2025 riscv64 riscv64 riscv64 GNU/Linux

The change-gateware.sh script no longer works, I used the polarfire instructions polarfire-soc-documentation/how-to/re-programming-the-fpga-from-linux.md at master · polarfire-soc/polarfire-soc-documentation to update:

sudo sh -c "echo '1' > /sys/class/firmware/mpfs-auto-update/loading"
sudo sh -c "cat /usr/share/beagleboard/gateware/default/LinuxProgramming/mpfs_bitstream.spi > /sys/class/firmware/mpfs-auto-update/data"
sudo sh -c "echo '0' > /sys/class/firmware/mpfs-auto-update/loading"

sudo sh -c "echo '1' > /sys/class/firmware/mpfs-auto-update/loading"
sudo sh -c "cat /usr/share/beagleboard/gateware/default/LinuxProgramming/mpfs_dtbo.spi > /sys/class/firmware/mpfs-auto-update/data"
sudo sh -c "echo '0' > /sys/class/firmware/mpfs-auto-update/loading"

The GPIO used previously has moved from gpiochip3 to gpiochip4

Using gpioset --mode=wait gpiochip4 10={0/1} generates the expected pin output levels.
-The output signal level is 3.28V

Connecting header IO pin P9_23 to P9_25

Using gpioget gpiochip4 12 does not detect the expected level of the pin.
-The signal level drops from 3.28V to 1.24V when connected
-Also gpiod_line_get_value now fails with Operation not permitted

Using gpiomon gpiochip4 12 fails with gpiomon: error waiting for events: No such device.
-Also gpiod_line_request_rising_edges_events now fails with No such device

However…
If I use pins from gpiochip2, say P8_15 and P8_17, then both gpioget and gpiomon work as expected

The default gateware cape indicates:

> |P8_15|MSS GPIO_2[12]|53|GPIO|
> |P8_17|MSS GPIO_2[14]|53|GPIO|
>
> |P9_25|core_gpio[12] @ 0x41200000|154|GPIO|
> |P9_27|core_gpio[14] @ 0x41200000|156|GPIO|

Could there be an underlying reason why core_gpio pins are not working as expected on my system?

Interesting. One thing I can tell you, is that the MSS_GPIOs are routed to internal
GPIO banks on the hard processor complex and the CORE_GPIOs are implemented
in the FPGA fabric. The interrupts are routed differently (if at all; haven’t looked specifically),
so you might just accidently have stumbled on either a bug in the fabric
or maybe the device-tree. @Vauban, your thoughts?

As to the update script, I was given this by Microchip as an interim workaround
until we can supply a more polished version that works with both 6.1 and 6.6.

The more I look at the device-tree, the more I start to suspect that the interrupt
mappings are missing from the gpio definitions:

	cape_gpios_p9: gpio@41200000 {
		compatible = "microchip,core-gpio", "microchip,coregpio-rtl-v3";
		reg = <0x0 0x41200000 0x0 0x1000>;
		clocks = <&fabric_clk3>;
		gpio-controller;
		#gpio-cells = <2>;
		ngpios = <21>;
		status = "okay";
		gpio-line-names = "", "P9_12", "", "", "P9_15",
				  "", "", "", "", "",
				  "P9_23", "", "P9_25", "", "P9_27",
				  "", "", "P9_30", "", "P9_41",
				  "";
	};

Let me see if I can’t cobble something together once I recover from a bad kernel crash…